2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/io/iomgr/rawfs.c
5 * PURPOSE: Raw File System Driver
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES *****************************************************************/
15 /* TYPES *******************************************************************/
21 PDEVICE_OBJECT TargetDeviceObject
;
26 SHARE_ACCESS ShareAccess
;
28 LARGE_INTEGER SectorsOnDisk
;
31 typedef struct _VOLUME_DEVICE_OBJECT
33 DEVICE_OBJECT DeviceObject
;
35 } VOLUME_DEVICE_OBJECT
, *PVOLUME_DEVICE_OBJECT
;
37 /* GLOBALS *******************************************************************/
39 PDEVICE_OBJECT RawDiskDeviceObject
, RawCdromDeviceObject
, RawTapeDeviceObject
;
41 /* FUNCTIONS *****************************************************************/
45 RawInitializeVcb(IN OUT PVCB Vcb
,
46 IN PDEVICE_OBJECT TargetDeviceObject
,
52 RtlZeroMemory(Vcb
, sizeof(VCB
));
54 /* Associate to system objects */
55 Vcb
->TargetDeviceObject
= TargetDeviceObject
;
58 /* Initialize the lock */
59 KeInitializeMutex(&Vcb
->Mutex
, 0);
64 RawCheckForDismount(IN PVCB Vcb
,
65 IN BOOLEAN CreateOperation
)
72 IoAcquireVpbSpinLock(&OldIrql
);
74 /* Reference it and check if a create is being done */
76 if (Vcb
->Vpb
->ReferenceCount
!= CreateOperation
)
78 /* Don't do anything */
83 /* Otherwise, delete the volume */
86 /* Check if it has a VPB and unmount it */
87 if (Vpb
->RealDevice
->Vpb
== Vpb
)
89 Vpb
->DeviceObject
= NULL
;
90 Vpb
->Flags
&= ~VPB_MOUNTED
;
94 /* Release lock and return status */
95 IoReleaseVpbSpinLock(OldIrql
);
101 RawCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
,
105 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
107 /* Check if this was a valid sync R/W request */
108 if (((IoStackLocation
->MajorFunction
== IRP_MJ_READ
) ||
109 (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)) &&
110 ((IoStackLocation
->FileObject
)) &&
111 (FlagOn(IoStackLocation
->FileObject
->Flags
, FO_SYNCHRONOUS_IO
)) &&
112 (NT_SUCCESS(Irp
->IoStatus
.Status
)))
114 /* Update byte offset */
115 IoStackLocation
->FileObject
->CurrentByteOffset
.QuadPart
+=
116 Irp
->IoStatus
.Information
;
119 /* Mark the IRP Pending if it was */
120 if (Irp
->PendingReturned
) IoMarkIrpPending(Irp
);
121 return STATUS_SUCCESS
;
126 RawClose(IN PVCB Vcb
,
128 IN PIO_STACK_LOCATION IoStackLocation
)
131 BOOLEAN Deleted
= FALSE
;
134 /* Make sure we can clean up */
135 Status
= KeWaitForSingleObject(&Vcb
->Mutex
,
140 ASSERT(NT_SUCCESS(Status
));
142 /* Decrease the open count and check if this is a dismount */
144 if (!Vcb
->OpenCount
) Deleted
= RawCheckForDismount(Vcb
, FALSE
);
146 /* Check if we should delete the device */
147 KeReleaseMutex(&Vcb
->Mutex
, FALSE
);
151 IoDeleteDevice((PDEVICE_OBJECT
)CONTAINING_RECORD(Vcb
,
152 VOLUME_DEVICE_OBJECT
,
156 /* Complete the request */
157 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
158 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
159 return STATUS_SUCCESS
;
164 RawCreate(IN PVCB Vcb
,
166 IN PIO_STACK_LOCATION IoStackLocation
)
169 BOOLEAN Deleted
= FALSE
;
171 ACCESS_MASK DesiredAccess
;
174 /* Make sure we can clean up */
175 Status
= KeWaitForSingleObject(&Vcb
->Mutex
,
180 ASSERT(NT_SUCCESS(Status
));
182 /* Check if this is a valid non-directory file open */
183 if ((!(IoStackLocation
->FileObject
) ||
184 !(IoStackLocation
->FileObject
->FileName
.Length
)) &&
185 ((IoStackLocation
->Parameters
.Create
.Options
>> 24) == FILE_OPEN
) &&
186 (!(IoStackLocation
->Parameters
.Create
.Options
& FILE_DIRECTORY_FILE
)))
188 /* Make sure the VCB isn't locked */
189 if (Vcb
->VcbState
& 1)
191 /* Refuse the operation */
192 Status
= STATUS_ACCESS_DENIED
;
193 Irp
->IoStatus
.Information
= 0;
197 /* Setup share access */
198 ShareAccess
= IoStackLocation
->Parameters
.Create
.ShareAccess
;
199 DesiredAccess
= IoStackLocation
->Parameters
.Create
.
200 SecurityContext
->DesiredAccess
;
202 /* Check if this VCB was already opened */
203 if (Vcb
->OpenCount
> 0)
205 /* Try to see if we have access to it */
206 Status
= IoCheckShareAccess(DesiredAccess
,
208 IoStackLocation
->FileObject
,
211 if (!NT_SUCCESS(Status
)) Irp
->IoStatus
.Information
= 0;
214 /* Make sure we have access */
215 if (NT_SUCCESS(Status
))
217 /* Check if this is the first open */
220 /* Set the share access */
221 IoSetShareAccess(DesiredAccess
,
223 IoStackLocation
->FileObject
,
227 /* Increase the open count and set the VPB */
229 IoStackLocation
->FileObject
->Vpb
= Vcb
->Vpb
;
231 /* Set IRP status and disable intermediate buffering */
232 Status
= STATUS_SUCCESS
;
233 Irp
->IoStatus
.Information
= FILE_OPENED
;
234 IoStackLocation
->FileObject
->Flags
|=
235 FO_NO_INTERMEDIATE_BUFFERING
;
241 /* Invalid create request */
242 Status
= STATUS_INVALID_PARAMETER
;
243 Irp
->IoStatus
.Information
= 0;
246 /* Check if the request failed */
247 if (!(NT_SUCCESS(Status
)) && !(Vcb
->OpenCount
))
249 /* Check if we can dismount the device */
250 Deleted
= RawCheckForDismount(Vcb
, FALSE
);
253 /* Check if we should delete the device */
254 KeReleaseMutex(&Vcb
->Mutex
, FALSE
);
258 IoDeleteDevice((PDEVICE_OBJECT
)CONTAINING_RECORD(Vcb
,
259 VOLUME_DEVICE_OBJECT
,
263 /* Complete the request */
264 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
265 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
266 return STATUS_SUCCESS
;
271 RawReadWriteDeviceControl(IN PVCB Vcb
,
273 IN PIO_STACK_LOCATION IoStackLocation
)
278 /* Don't do anything if the request was 0 bytes */
279 if (((IoStackLocation
->MajorFunction
== IRP_MJ_READ
) ||
280 (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)) &&
281 !(IoStackLocation
->Parameters
.Read
.Length
))
284 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
285 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
286 return STATUS_SUCCESS
;
289 /* Copy the IRP stack location */
290 IoCopyCurrentIrpStackLocationToNext(Irp
);
292 /* Disable verifies */
293 IoGetNextIrpStackLocation(Irp
)->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
295 /* Setup a completion routine */
296 IoSetCompletionRoutine(Irp
,
297 RawCompletionRoutine
,
303 /* Call the next driver and exit */
304 Status
= IoCallDriver(Vcb
->TargetDeviceObject
, Irp
);
310 RawMountVolume(IN PIO_STACK_LOCATION IoStackLocation
)
313 PDEVICE_OBJECT DeviceObject
;
314 PVOLUME_DEVICE_OBJECT Volume
;
315 PFILE_OBJECT FileObject
= NULL
;
318 /* Remember our owner */
319 DeviceObject
= IoStackLocation
->Parameters
.MountVolume
.DeviceObject
;
321 /* Create the volume */
322 Status
= IoCreateDevice(RawDiskDeviceObject
->DriverObject
,
323 sizeof(VOLUME_DEVICE_OBJECT
) -
324 sizeof(DEVICE_OBJECT
),
326 FILE_DEVICE_DISK_FILE_SYSTEM
,
329 (PDEVICE_OBJECT
*)&Volume
);
330 if (!NT_SUCCESS(Status
)) return Status
;
332 /* Use highest alignment requirement */
333 Volume
->DeviceObject
.AlignmentRequirement
= max(DeviceObject
->
334 AlignmentRequirement
,
335 Volume
->DeviceObject
.
336 AlignmentRequirement
);
339 RawInitializeVcb(&Volume
->Vcb
,
340 IoStackLocation
->Parameters
.MountVolume
.DeviceObject
,
341 IoStackLocation
->Parameters
.MountVolume
.Vpb
);
343 /* Set dummy label and serial number */
344 Volume
->Vcb
.Vpb
->SerialNumber
= 0xFFFFFFFF;
345 Volume
->Vcb
.Vpb
->VolumeLabelLength
= 0;
348 Volume
->Vcb
.Vpb
->DeviceObject
= &Volume
->DeviceObject
;
349 Volume
->DeviceObject
.StackSize
= DeviceObject
->StackSize
+ 1;
350 Volume
->DeviceObject
.SectorSize
= DeviceObject
->SectorSize
;
351 Volume
->DeviceObject
.Flags
|= DO_DIRECT_IO
;
352 Volume
->DeviceObject
.Flags
&= ~DO_DEVICE_INITIALIZING
;
354 /* Try to get associated FO (for notification) */
357 FileObject
= IoCreateStreamFileObjectLite(NULL
,
358 &(Volume
->DeviceObject
));
360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
362 /* Get the exception code */
363 Status
= _SEH2_GetExceptionCode();
367 /* If failed, delete devive */
368 if (!NT_SUCCESS(Status
))
370 IoDeleteDevice((PDEVICE_OBJECT
)Volume
);
374 /* Increment OpenCount by two to avoid dismount when RawClose() will be called on ObDereferenceObject() */
375 Volume
->Vcb
.OpenCount
+= 2;
376 /* Notify for sucessful mount */
377 FsRtlNotifyVolumeEvent(FileObject
, FSRTL_VOLUME_MOUNT
);
378 /* Decrease refcount to 0 to make FileObject being released */
379 ObDereferenceObject(FileObject
);
380 /* It's not open anymore, go back to 0 */
381 Volume
->Vcb
.OpenCount
-= 2;
388 RawUserFsCtrl(IN PIO_STACK_LOCATION IoStackLocation
,
394 /* Lock the device */
395 Status
= KeWaitForSingleObject(&Vcb
->Mutex
,
400 ASSERT(NT_SUCCESS(Status
));
402 /* Check what kind of request this is */
403 switch (IoStackLocation
->Parameters
.FileSystemControl
.FsControlCode
)
405 /* Oplock requests */
406 case FSCTL_REQUEST_OPLOCK_LEVEL_1
:
407 case FSCTL_REQUEST_OPLOCK_LEVEL_2
:
408 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
:
409 case FSCTL_OPLOCK_BREAK_NOTIFY
:
411 /* We don't handle them */
412 Status
= STATUS_NOT_IMPLEMENTED
;
416 case FSCTL_LOCK_VOLUME
:
418 /* Make sure we're not locked, and that we're alone */
419 if (!(Vcb
->VcbState
& 1) && (Vcb
->OpenCount
== 1))
423 Status
= STATUS_SUCCESS
;
427 /* Otherwise, we can't do this */
428 Status
= STATUS_ACCESS_DENIED
;
433 case FSCTL_UNLOCK_VOLUME
:
435 /* Make sure we're locked */
436 if (!(Vcb
->VcbState
& 1))
438 /* Let caller know we're not */
439 Status
= STATUS_NOT_LOCKED
;
445 Status
= STATUS_SUCCESS
;
449 /* Dismount request */
450 case FSCTL_DISMOUNT_VOLUME
:
452 /* Make sure we're locked */
453 if (Vcb
->VcbState
& 1)
455 /* Do nothing, just return success */
456 Status
= STATUS_SUCCESS
;
460 /* We can't dismount, device not locked */
461 Status
= STATUS_ACCESS_DENIED
;
465 /* Unknown request */
469 Status
= STATUS_INVALID_PARAMETER
;
474 KeReleaseMutex(&Vcb
->Mutex
, FALSE
);
476 /* In case of status change, notify */
477 switch (IoStackLocation
->Parameters
.FileSystemControl
.FsControlCode
)
479 case FSCTL_LOCK_VOLUME
:
480 FsRtlNotifyVolumeEvent(IoStackLocation
->FileObject
, (NT_SUCCESS(Status
) ? FSRTL_VOLUME_LOCK
: FSRTL_VOLUME_LOCK_FAILED
));
482 case FSCTL_UNLOCK_VOLUME
:
483 if (NT_SUCCESS(Status
))
485 FsRtlNotifyVolumeEvent(IoStackLocation
->FileObject
, FSRTL_VOLUME_UNLOCK
);
488 case FSCTL_DISMOUNT_VOLUME
:
489 FsRtlNotifyVolumeEvent(IoStackLocation
->FileObject
, (NT_SUCCESS(Status
) ? FSRTL_VOLUME_DISMOUNT
: FSRTL_VOLUME_DISMOUNT_FAILED
));
498 RawFileSystemControl(IN PVCB Vcb
,
500 IN PIO_STACK_LOCATION IoStackLocation
)
505 /* Check the kinds of FSCTLs that we support */
506 switch (IoStackLocation
->MinorFunction
)
508 /* User-mode request */
509 case IRP_MN_USER_FS_REQUEST
:
512 Status
= RawUserFsCtrl(IoStackLocation
, Vcb
);
516 case IRP_MN_MOUNT_VOLUME
:
518 /* Mount the volume */
519 Status
= RawMountVolume(IoStackLocation
);
522 case IRP_MN_VERIFY_VOLUME
:
524 /* We don't do verifies */
525 Status
= STATUS_WRONG_VOLUME
;
526 Vcb
->Vpb
->RealDevice
->Flags
&= ~DO_VERIFY_VOLUME
;
528 /* Check if we should delete the device */
529 if (RawCheckForDismount(Vcb
, FALSE
))
532 IoDeleteDevice((PDEVICE_OBJECT
)
533 CONTAINING_RECORD(Vcb
,
534 VOLUME_DEVICE_OBJECT
,
541 /* Invalid request */
545 Status
= STATUS_INVALID_DEVICE_REQUEST
;
549 /* Complete the request */
550 Irp
->IoStatus
.Status
= Status
;
551 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
557 RawQueryInformation(IN PVCB Vcb
,
559 IN PIO_STACK_LOCATION IoStackLocation
)
561 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
563 PFILE_POSITION_INFORMATION Buffer
;
566 /* Get information from the IRP */
567 Length
= &IoStackLocation
->Parameters
.QueryFile
.Length
;
568 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
570 /* We only handle this request */
571 if (IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
==
572 FilePositionInformation
)
574 /* Validate buffer size */
575 if (*Length
< sizeof(FILE_POSITION_INFORMATION
))
578 Irp
->IoStatus
.Information
= 0;
579 Status
= STATUS_BUFFER_OVERFLOW
;
583 /* Get offset and update length */
584 Buffer
->CurrentByteOffset
= IoStackLocation
->FileObject
->
586 *Length
-= sizeof(FILE_POSITION_INFORMATION
);
588 /* Set IRP Status information */
589 Irp
->IoStatus
.Information
= sizeof(FILE_POSITION_INFORMATION
);
590 Status
= STATUS_SUCCESS
;
595 Irp
->IoStatus
.Status
= Status
;
596 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
602 RawSetInformation(IN PVCB Vcb
,
604 IN PIO_STACK_LOCATION IoStackLocation
)
606 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
607 PFILE_POSITION_INFORMATION Buffer
;
608 PDEVICE_OBJECT DeviceObject
;
611 /* Get information from the IRP */
612 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
614 /* We only handle this request */
615 if (IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
==
616 FilePositionInformation
)
619 DeviceObject
= IoGetRelatedDeviceObject(IoStackLocation
->FileObject
);
621 /* Make sure the offset is aligned */
622 if ((Buffer
->CurrentByteOffset
.LowPart
&
623 DeviceObject
->AlignmentRequirement
))
626 Status
= STATUS_INVALID_PARAMETER
;
630 /* Otherwise, set offset */
631 IoStackLocation
->FileObject
->CurrentByteOffset
= Buffer
->
634 /* Set IRP Status information */
635 Status
= STATUS_SUCCESS
;
640 Irp
->IoStatus
.Status
= Status
;
641 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
647 RawQueryFsVolumeInfo(IN PVCB Vcb
,
648 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
649 IN OUT PULONG Length
)
653 /* Clear the buffer and stub it out */
654 RtlZeroMemory( Buffer
, sizeof(FILE_FS_VOLUME_INFORMATION
));
655 Buffer
->VolumeSerialNumber
= Vcb
->Vpb
->SerialNumber
;
656 Buffer
->SupportsObjects
= FALSE
;
657 Buffer
->VolumeLabelLength
= 0;
659 /* Return length and success */
660 *Length
-= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
[0]);
661 return STATUS_SUCCESS
;
666 RawQueryFsSizeInfo(IN PVCB Vcb
,
667 IN PFILE_FS_SIZE_INFORMATION Buffer
,
668 IN OUT PULONG Length
)
673 IO_STATUS_BLOCK IoStatusBlock
;
674 PDEVICE_OBJECT RealDevice
;
675 DISK_GEOMETRY DiskGeometry
;
676 PARTITION_INFORMATION PartitionInformation
;
677 BOOLEAN DiskHasPartitions
;
680 /* Validate the buffer */
681 if (*Length
< sizeof(FILE_FS_SIZE_INFORMATION
))
684 return STATUS_BUFFER_OVERFLOW
;
687 /* Clear the buffer, initialize the event and set the DO */
688 RtlZeroMemory(Buffer
, sizeof(FILE_FS_SIZE_INFORMATION
));
689 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
690 RealDevice
= Vcb
->Vpb
->RealDevice
;
692 /* Build query IRP */
693 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
698 sizeof(DISK_GEOMETRY
),
702 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
704 /* Call driver and check if we're pending */
705 Status
= IoCallDriver(RealDevice
, Irp
);
706 if (Status
== STATUS_PENDING
)
708 /* Wait on driver to finish */
709 KeWaitForSingleObject(&Event
,
714 Status
= IoStatusBlock
.Status
;
717 /* Fail if we couldn't get CHS data */
718 if (!NT_SUCCESS(Status
))
724 /* Check if this is a floppy */
725 if (FlagOn(RealDevice
->Characteristics
, FILE_FLOPPY_DISKETTE
))
727 /* Floppies don't have partitions */
728 DiskHasPartitions
= FALSE
;
732 /* Setup query IRP */
733 KeResetEvent(&Event
);
734 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
738 &PartitionInformation
,
739 sizeof(PARTITION_INFORMATION
),
743 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
745 /* Call driver and check if we're pending */
746 Status
= IoCallDriver(RealDevice
, Irp
);
747 if (Status
== STATUS_PENDING
)
749 /* Wait on driver to finish */
750 KeWaitForSingleObject(&Event
,
755 Status
= IoStatusBlock
.Status
;
758 /* If this was an invalid request, then the disk is not partitioned */
759 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
761 DiskHasPartitions
= FALSE
;
765 /* Otherwise, it must be */
766 ASSERT(NT_SUCCESS(Status
));
767 DiskHasPartitions
= TRUE
;
771 /* Set sector data */
772 Buffer
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
773 Buffer
->SectorsPerAllocationUnit
= 1;
775 /* Calculate allocation units */
776 if (DiskHasPartitions
)
778 /* Use partition data */
779 Buffer
->TotalAllocationUnits
=
780 RtlExtendedLargeIntegerDivide(PartitionInformation
.PartitionLength
,
781 DiskGeometry
.BytesPerSector
,
787 Buffer
->TotalAllocationUnits
=
788 RtlExtendedIntegerMultiply(DiskGeometry
.Cylinders
,
789 DiskGeometry
.TracksPerCylinder
*
790 DiskGeometry
.SectorsPerTrack
);
793 /* Set available units */
794 Buffer
->AvailableAllocationUnits
= Buffer
->TotalAllocationUnits
;
796 /* Return length and success */
797 *Length
-= sizeof(FILE_FS_SIZE_INFORMATION
);
798 return STATUS_SUCCESS
;
803 RawQueryFsDeviceInfo(IN PVCB Vcb
,
804 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
805 IN OUT PULONG Length
)
809 /* Validate buffer */
810 if (*Length
< sizeof(FILE_FS_DEVICE_INFORMATION
))
813 return STATUS_BUFFER_OVERFLOW
;
816 /* Clear buffer and write information */
817 RtlZeroMemory(Buffer
, sizeof(FILE_FS_DEVICE_INFORMATION
));
818 Buffer
->DeviceType
= FILE_DEVICE_DISK
;
819 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
;
821 /* Return length and success */
822 *Length
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
823 return STATUS_SUCCESS
;
828 RawQueryFsAttributeInfo(IN PVCB Vcb
,
829 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
830 IN OUT PULONG Length
)
832 const WCHAR szRawFSName
[] = L
"RAW";
836 /* Check if the buffer is large enough for our name ("RAW") */
837 ReturnLength
= FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION
,
838 FileSystemName
[sizeof(szRawFSName
) / sizeof(szRawFSName
[0])]);
839 if (*Length
< ReturnLength
) return STATUS_BUFFER_OVERFLOW
;
841 /* Output the data */
842 Buffer
->FileSystemAttributes
= 0;
843 Buffer
->MaximumComponentNameLength
= 0;
844 Buffer
->FileSystemNameLength
= 6;
845 RtlCopyMemory(&Buffer
->FileSystemName
[0], szRawFSName
, sizeof(szRawFSName
));
847 /* Return length and success */
848 *Length
-= ReturnLength
;
849 return STATUS_SUCCESS
;
854 RawQueryVolumeInformation(IN PVCB Vcb
,
856 IN PIO_STACK_LOCATION IoStackLocation
)
864 Length
= IoStackLocation
->Parameters
.QueryVolume
.Length
;
865 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
867 /* Check the kind of request */
868 switch (IoStackLocation
->Parameters
.QueryVolume
.FsInformationClass
)
870 /* Volume information request */
871 case FileFsVolumeInformation
:
873 Status
= RawQueryFsVolumeInfo(Vcb
, Buffer
, &Length
);
876 /* File system size invormation */
877 case FileFsSizeInformation
:
879 Status
= RawQueryFsSizeInfo(Vcb
, Buffer
, &Length
);
882 /* Device information */
883 case FileFsDeviceInformation
:
885 Status
= RawQueryFsDeviceInfo(Vcb
, Buffer
, &Length
);
888 /* Attribute information */
889 case FileFsAttributeInformation
:
891 Status
= RawQueryFsAttributeInfo(Vcb
, Buffer
, &Length
);
894 /* Invalid request */
898 Status
= STATUS_INVALID_PARAMETER
;
902 /* Set status and complete the request */
903 Irp
->IoStatus
.Information
= IoStackLocation
->
904 Parameters
.QueryVolume
.Length
- Length
;
905 Irp
->IoStatus
.Status
= Status
;
906 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
912 RawCleanup(IN PVCB Vcb
,
914 IN PIO_STACK_LOCATION IoStackLocation
)
919 /* Make sure we can clean up */
920 Status
= KeWaitForSingleObject(&Vcb
->Mutex
,
925 ASSERT(NT_SUCCESS(Status
));
927 /* Remove shared access and complete the request */
928 IoRemoveShareAccess(IoStackLocation
->FileObject
, &Vcb
->ShareAccess
);
929 KeReleaseMutex(&Vcb
->Mutex
, FALSE
);
930 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
931 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
932 return STATUS_SUCCESS
;
937 RawDispatch(IN PVOLUME_DEVICE_OBJECT DeviceObject
,
940 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
941 PIO_STACK_LOCATION IoStackLocation
;
945 /* Get the stack location */
946 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
948 /* Differentiate between Volume DO and FS DO */
949 if ((((PDEVICE_OBJECT
)DeviceObject
)->Size
== sizeof(DEVICE_OBJECT
)) &&
950 !((IoStackLocation
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
) &&
951 (IoStackLocation
->MinorFunction
== IRP_MN_MOUNT_VOLUME
)))
953 /* This is an FS DO. Stub out the common calls */
954 if ((IoStackLocation
->MajorFunction
== IRP_MJ_CREATE
) ||
955 (IoStackLocation
->MajorFunction
== IRP_MJ_CLEANUP
) ||
956 (IoStackLocation
->MajorFunction
== IRP_MJ_CLOSE
))
958 /* Return success for them */
959 Status
= STATUS_SUCCESS
;
963 /* Anything else, we don't support */
964 Status
= STATUS_INVALID_DEVICE_REQUEST
;
967 /* Complete the request */
968 Irp
->IoStatus
.Status
= Status
;
969 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
973 /* Otherwise, get our VCB and start handling the IRP */
974 FsRtlEnterFileSystem();
975 Vcb
= &DeviceObject
->Vcb
;
977 /* Check what kind of IRP this is */
978 switch (IoStackLocation
->MajorFunction
)
980 /* Cleanup request */
983 Status
= RawCleanup(Vcb
, Irp
, IoStackLocation
);
989 Status
= RawClose(Vcb
, Irp
, IoStackLocation
);
995 Status
= RawCreate(Vcb
, Irp
, IoStackLocation
);
999 case IRP_MJ_FILE_SYSTEM_CONTROL
:
1001 Status
= RawFileSystemControl(Vcb
, Irp
, IoStackLocation
);
1004 /* R/W or IOCTL request */
1007 case IRP_MJ_DEVICE_CONTROL
:
1009 Status
= RawReadWriteDeviceControl(Vcb
, Irp
, IoStackLocation
);
1012 /* Information query request */
1013 case IRP_MJ_QUERY_INFORMATION
:
1015 Status
= RawQueryInformation(Vcb
, Irp
, IoStackLocation
);
1018 /* Information set request */
1019 case IRP_MJ_SET_INFORMATION
:
1021 Status
= RawSetInformation(Vcb
, Irp
, IoStackLocation
);
1024 /* Volume information request */
1025 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
1027 Status
= RawQueryVolumeInformation(Vcb
, Irp
, IoStackLocation
);
1030 /* Unexpected request */
1033 /* Anything else is pretty bad */
1034 KeBugCheck(FILE_SYSTEM
);
1037 /* Return the status */
1038 FsRtlExitFileSystem();
1044 RawShutdown(IN PDEVICE_OBJECT DeviceObject
,
1047 /* Unregister file systems */
1048 #if 0 // FIXME: This freezes ROS at shutdown. PnP Problem?
1049 IoUnregisterFileSystem(RawDiskDeviceObject
);
1050 IoUnregisterFileSystem(RawCdromDeviceObject
);
1051 IoUnregisterFileSystem(RawTapeDeviceObject
);
1053 /* Delete the devices */
1054 IoDeleteDevice(RawDiskDeviceObject
);
1055 IoDeleteDevice(RawCdromDeviceObject
);
1056 IoDeleteDevice(RawTapeDeviceObject
);
1059 /* Complete the request */
1060 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1061 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1062 return STATUS_SUCCESS
;
1067 RawUnload(IN PDRIVER_OBJECT DriverObject
)
1069 #if 0 // FIXME: DriverUnload is never called
1070 /* Dereference device objects */
1071 ObDereferenceObject(RawDiskDeviceObject
);
1072 ObDereferenceObject(RawCdromDeviceObject
);
1073 ObDereferenceObject(RawTapeDeviceObject
);
1080 RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject
,
1081 IN PUNICODE_STRING RegistryPath
)
1083 UNICODE_STRING DeviceName
;
1086 /* Create the raw disk device */
1087 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawDisk");
1088 Status
= IoCreateDevice(DriverObject
,
1091 FILE_DEVICE_DISK_FILE_SYSTEM
,
1094 &RawDiskDeviceObject
);
1095 if (!NT_SUCCESS(Status
)) return Status
;
1097 /* Create the raw CDROM device */
1098 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawCdRom");
1099 Status
= IoCreateDevice(DriverObject
,
1102 FILE_DEVICE_CD_ROM_FILE_SYSTEM
,
1105 &RawCdromDeviceObject
);
1106 if (!NT_SUCCESS(Status
)) return Status
;
1108 /* Create the raw tape device */
1109 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawTape");
1110 Status
= IoCreateDevice(DriverObject
,
1113 FILE_DEVICE_TAPE_FILE_SYSTEM
,
1116 &RawTapeDeviceObject
);
1117 if (!NT_SUCCESS(Status
)) return Status
;
1119 /* Set Direct I/O for all devices */
1120 RawDiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
1121 RawCdromDeviceObject
->Flags
|= DO_DIRECT_IO
;
1122 RawTapeDeviceObject
->Flags
|= DO_DIRECT_IO
;
1124 /* Set generic stubs */
1125 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] =
1126 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] =
1127 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] =
1128 DriverObject
->MajorFunction
[IRP_MJ_READ
] =
1129 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
1130 DriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] =
1131 DriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] =
1132 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] =
1133 DriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] =
1134 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = (PDRIVER_DISPATCH
)RawDispatch
;
1136 /* Shutdown and unload */
1137 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = RawShutdown
;
1138 DriverObject
->DriverUnload
= RawUnload
;
1140 /* Register the file systems */
1141 IoRegisterFileSystem(RawDiskDeviceObject
);
1142 IoRegisterFileSystem(RawCdromDeviceObject
);
1143 IoRegisterFileSystem(RawTapeDeviceObject
);
1145 #if 0 // FIXME: DriverUnload is never called
1146 /* Reference device objects */
1147 ObReferenceObject(RawDiskDeviceObject
);
1148 ObReferenceObject(RawCdromDeviceObject
);
1149 ObReferenceObject(RawTapeDeviceObject
);
1151 return STATUS_SUCCESS
;