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
;
608 PFILE_POSITION_INFORMATION Buffer
;
609 PDEVICE_OBJECT DeviceObject
;
612 /* Get information from the IRP */
613 Length
= &IoStackLocation
->Parameters
.QueryFile
.Length
;
614 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
616 /* We only handle this request */
617 if (IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
==
618 FilePositionInformation
)
621 DeviceObject
= IoGetRelatedDeviceObject(IoStackLocation
->FileObject
);
623 /* Make sure the offset is aligned */
624 if ((Buffer
->CurrentByteOffset
.LowPart
&
625 DeviceObject
->AlignmentRequirement
))
628 Status
= STATUS_INVALID_PARAMETER
;
632 /* Otherwise, set offset */
633 IoStackLocation
->FileObject
->CurrentByteOffset
= Buffer
->
636 /* Set IRP Status information */
637 Status
= STATUS_SUCCESS
;
642 Irp
->IoStatus
.Status
= Status
;
643 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
649 RawQueryFsVolumeInfo(IN PVCB Vcb
,
650 IN PFILE_FS_VOLUME_INFORMATION Buffer
,
651 IN OUT PULONG Length
)
655 /* Clear the buffer and stub it out */
656 RtlZeroMemory( Buffer
, sizeof(FILE_FS_VOLUME_INFORMATION
));
657 Buffer
->VolumeSerialNumber
= Vcb
->Vpb
->SerialNumber
;
658 Buffer
->SupportsObjects
= FALSE
;
659 Buffer
->VolumeLabelLength
= 0;
661 /* Return length and success */
662 *Length
-= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION
, VolumeLabel
[0]);
663 return STATUS_SUCCESS
;
668 RawQueryFsSizeInfo(IN PVCB Vcb
,
669 IN PFILE_FS_SIZE_INFORMATION Buffer
,
670 IN OUT PULONG Length
)
675 IO_STATUS_BLOCK IoStatusBlock
;
676 PDEVICE_OBJECT RealDevice
;
677 DISK_GEOMETRY DiskGeometry
;
678 PARTITION_INFORMATION PartitionInformation
;
679 BOOLEAN DiskHasPartitions
;
682 /* Validate the buffer */
683 if (*Length
< sizeof(FILE_FS_SIZE_INFORMATION
))
686 return STATUS_BUFFER_OVERFLOW
;
689 /* Clear the buffer, initialize the event and set the DO */
690 RtlZeroMemory(Buffer
, sizeof(FILE_FS_SIZE_INFORMATION
));
691 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
692 RealDevice
= Vcb
->Vpb
->RealDevice
;
694 /* Build query IRP */
695 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
700 sizeof(DISK_GEOMETRY
),
704 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
706 /* Call driver and check if we're pending */
707 Status
= IoCallDriver(RealDevice
, Irp
);
708 if (Status
== STATUS_PENDING
)
710 /* Wait on driver to finish */
711 KeWaitForSingleObject(&Event
,
716 Status
= IoStatusBlock
.Status
;
719 /* Fail if we couldn't get CHS data */
720 if (!NT_SUCCESS(Status
))
726 /* Check if this is a floppy */
727 if (FlagOn(RealDevice
->Characteristics
, FILE_FLOPPY_DISKETTE
))
729 /* Floppies don't have partitions */
730 DiskHasPartitions
= FALSE
;
734 /* Setup query IRP */
735 KeResetEvent(&Event
);
736 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
740 &PartitionInformation
,
741 sizeof(PARTITION_INFORMATION
),
745 if (!Irp
) return STATUS_INSUFFICIENT_RESOURCES
;
747 /* Call driver and check if we're pending */
748 Status
= IoCallDriver(RealDevice
, Irp
);
749 if (Status
== STATUS_PENDING
)
751 /* Wait on driver to finish */
752 KeWaitForSingleObject(&Event
,
757 Status
= IoStatusBlock
.Status
;
760 /* If this was an invalid request, then the disk is not partitioned */
761 if (Status
== STATUS_INVALID_DEVICE_REQUEST
)
763 DiskHasPartitions
= FALSE
;
767 /* Otherwise, it must be */
768 ASSERT(NT_SUCCESS(Status
));
769 DiskHasPartitions
= TRUE
;
773 /* Set sector data */
774 Buffer
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
775 Buffer
->SectorsPerAllocationUnit
= 1;
777 /* Calculate allocation units */
778 if (DiskHasPartitions
)
780 /* Use partition data */
781 Buffer
->TotalAllocationUnits
=
782 RtlExtendedLargeIntegerDivide(PartitionInformation
.PartitionLength
,
783 DiskGeometry
.BytesPerSector
,
789 Buffer
->TotalAllocationUnits
=
790 RtlExtendedIntegerMultiply(DiskGeometry
.Cylinders
,
791 DiskGeometry
.TracksPerCylinder
*
792 DiskGeometry
.SectorsPerTrack
);
795 /* Set available units */
796 Buffer
->AvailableAllocationUnits
= Buffer
->TotalAllocationUnits
;
798 /* Return length and success */
799 *Length
-= sizeof(FILE_FS_SIZE_INFORMATION
);
800 return STATUS_SUCCESS
;
805 RawQueryFsDeviceInfo(IN PVCB Vcb
,
806 IN PFILE_FS_DEVICE_INFORMATION Buffer
,
807 IN OUT PULONG Length
)
811 /* Validate buffer */
812 if (*Length
< sizeof(FILE_FS_DEVICE_INFORMATION
))
815 return STATUS_BUFFER_OVERFLOW
;
818 /* Clear buffer and write information */
819 RtlZeroMemory(Buffer
, sizeof(FILE_FS_DEVICE_INFORMATION
));
820 Buffer
->DeviceType
= FILE_DEVICE_DISK
;
821 Buffer
->Characteristics
= Vcb
->TargetDeviceObject
->Characteristics
;
823 /* Return length and success */
824 *Length
-= sizeof(FILE_FS_DEVICE_INFORMATION
);
825 return STATUS_SUCCESS
;
830 RawQueryFsAttributeInfo(IN PVCB Vcb
,
831 IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer
,
832 IN OUT PULONG Length
)
834 const WCHAR szRawFSName
[] = L
"RAW";
838 /* Check if the buffer is large enough for our name ("RAW") */
839 ReturnLength
= FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION
,
840 FileSystemName
[sizeof(szRawFSName
) / sizeof(szRawFSName
[0])]);
841 if (*Length
< ReturnLength
) return STATUS_BUFFER_OVERFLOW
;
843 /* Output the data */
844 Buffer
->FileSystemAttributes
= 0;
845 Buffer
->MaximumComponentNameLength
= 0;
846 Buffer
->FileSystemNameLength
= 6;
847 RtlCopyMemory(&Buffer
->FileSystemName
[0], szRawFSName
, sizeof(szRawFSName
));
849 /* Return length and success */
850 *Length
-= ReturnLength
;
851 return STATUS_SUCCESS
;
856 RawQueryVolumeInformation(IN PVCB Vcb
,
858 IN PIO_STACK_LOCATION IoStackLocation
)
866 Length
= IoStackLocation
->Parameters
.QueryVolume
.Length
;
867 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
869 /* Check the kind of request */
870 switch (IoStackLocation
->Parameters
.QueryVolume
.FsInformationClass
)
872 /* Volume information request */
873 case FileFsVolumeInformation
:
875 Status
= RawQueryFsVolumeInfo(Vcb
, Buffer
, &Length
);
878 /* File system size invormation */
879 case FileFsSizeInformation
:
881 Status
= RawQueryFsSizeInfo(Vcb
, Buffer
, &Length
);
884 /* Device information */
885 case FileFsDeviceInformation
:
887 Status
= RawQueryFsDeviceInfo(Vcb
, Buffer
, &Length
);
890 /* Attribute information */
891 case FileFsAttributeInformation
:
893 Status
= RawQueryFsAttributeInfo(Vcb
, Buffer
, &Length
);
896 /* Invalid request */
900 Status
= STATUS_INVALID_PARAMETER
;
904 /* Set status and complete the request */
905 Irp
->IoStatus
.Information
= IoStackLocation
->
906 Parameters
.QueryVolume
.Length
- Length
;
907 Irp
->IoStatus
.Status
= Status
;
908 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
914 RawCleanup(IN PVCB Vcb
,
916 IN PIO_STACK_LOCATION IoStackLocation
)
921 /* Make sure we can clean up */
922 Status
= KeWaitForSingleObject(&Vcb
->Mutex
,
927 ASSERT(NT_SUCCESS(Status
));
929 /* Remove shared access and complete the request */
930 IoRemoveShareAccess(IoStackLocation
->FileObject
, &Vcb
->ShareAccess
);
931 KeReleaseMutex(&Vcb
->Mutex
, FALSE
);
932 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
933 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
934 return STATUS_SUCCESS
;
939 RawDispatch(IN PVOLUME_DEVICE_OBJECT DeviceObject
,
942 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
943 PIO_STACK_LOCATION IoStackLocation
;
947 /* Get the stack location */
948 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
950 /* Differentiate between Volume DO and FS DO */
951 if ((((PDEVICE_OBJECT
)DeviceObject
)->Size
== sizeof(DEVICE_OBJECT
)) &&
952 !((IoStackLocation
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
) &&
953 (IoStackLocation
->MinorFunction
== IRP_MN_MOUNT_VOLUME
)))
955 /* This is an FS DO. Stub out the common calls */
956 if ((IoStackLocation
->MajorFunction
== IRP_MJ_CREATE
) ||
957 (IoStackLocation
->MajorFunction
== IRP_MJ_CLEANUP
) ||
958 (IoStackLocation
->MajorFunction
== IRP_MJ_CLOSE
))
960 /* Return success for them */
961 Status
= STATUS_SUCCESS
;
965 /* Anything else, we don't support */
966 Status
= STATUS_INVALID_DEVICE_REQUEST
;
969 /* Complete the request */
970 Irp
->IoStatus
.Status
= Status
;
971 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
975 /* Otherwise, get our VCB and start handling the IRP */
976 FsRtlEnterFileSystem();
977 Vcb
= &DeviceObject
->Vcb
;
979 /* Check what kind of IRP this is */
980 switch (IoStackLocation
->MajorFunction
)
982 /* Cleanup request */
985 Status
= RawCleanup(Vcb
, Irp
, IoStackLocation
);
991 Status
= RawClose(Vcb
, Irp
, IoStackLocation
);
997 Status
= RawCreate(Vcb
, Irp
, IoStackLocation
);
1001 case IRP_MJ_FILE_SYSTEM_CONTROL
:
1003 Status
= RawFileSystemControl(Vcb
, Irp
, IoStackLocation
);
1006 /* R/W or IOCTL request */
1009 case IRP_MJ_DEVICE_CONTROL
:
1011 Status
= RawReadWriteDeviceControl(Vcb
, Irp
, IoStackLocation
);
1014 /* Information query request */
1015 case IRP_MJ_QUERY_INFORMATION
:
1017 Status
= RawQueryInformation(Vcb
, Irp
, IoStackLocation
);
1020 /* Information set request */
1021 case IRP_MJ_SET_INFORMATION
:
1023 Status
= RawSetInformation(Vcb
, Irp
, IoStackLocation
);
1026 /* Volume information request */
1027 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
1029 Status
= RawQueryVolumeInformation(Vcb
, Irp
, IoStackLocation
);
1032 /* Unexpected request */
1035 /* Anything else is pretty bad */
1036 KeBugCheck(FILE_SYSTEM
);
1039 /* Return the status */
1040 FsRtlExitFileSystem();
1046 RawShutdown(IN PDEVICE_OBJECT DeviceObject
,
1049 /* Unregister file systems */
1050 #if 0 // FIXME: This freezes ROS at shutdown. PnP Problem?
1051 IoUnregisterFileSystem(RawDiskDeviceObject
);
1052 IoUnregisterFileSystem(RawCdromDeviceObject
);
1053 IoUnregisterFileSystem(RawTapeDeviceObject
);
1055 /* Delete the devices */
1056 IoDeleteDevice(RawDiskDeviceObject
);
1057 IoDeleteDevice(RawCdromDeviceObject
);
1058 IoDeleteDevice(RawTapeDeviceObject
);
1061 /* Complete the request */
1062 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1063 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1064 return STATUS_SUCCESS
;
1069 RawUnload(IN PDRIVER_OBJECT DriverObject
)
1071 #if 0 // FIXME: DriverUnload is never called
1072 /* Dereference device objects */
1073 ObDereferenceObject(RawDiskDeviceObject
);
1074 ObDereferenceObject(RawCdromDeviceObject
);
1075 ObDereferenceObject(RawTapeDeviceObject
);
1081 RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject
,
1082 IN PUNICODE_STRING RegistryPath
)
1084 UNICODE_STRING DeviceName
;
1087 /* Create the raw disk device */
1088 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawDisk");
1089 Status
= IoCreateDevice(DriverObject
,
1092 FILE_DEVICE_DISK_FILE_SYSTEM
,
1095 &RawDiskDeviceObject
);
1096 if (!NT_SUCCESS(Status
)) return Status
;
1098 /* Create the raw CDROM device */
1099 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawCdRom");
1100 Status
= IoCreateDevice(DriverObject
,
1103 FILE_DEVICE_CD_ROM_FILE_SYSTEM
,
1106 &RawCdromDeviceObject
);
1107 if (!NT_SUCCESS(Status
)) return Status
;
1109 /* Create the raw tape device */
1110 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\RawTape");
1111 Status
= IoCreateDevice(DriverObject
,
1114 FILE_DEVICE_TAPE_FILE_SYSTEM
,
1117 &RawTapeDeviceObject
);
1118 if (!NT_SUCCESS(Status
)) return Status
;
1120 /* Set Direct I/O for all devices */
1121 RawDiskDeviceObject
->Flags
|= DO_DIRECT_IO
;
1122 RawCdromDeviceObject
->Flags
|= DO_DIRECT_IO
;
1123 RawTapeDeviceObject
->Flags
|= DO_DIRECT_IO
;
1125 /* Set generic stubs */
1126 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] =
1127 DriverObject
->MajorFunction
[IRP_MJ_CLEANUP
] =
1128 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] =
1129 DriverObject
->MajorFunction
[IRP_MJ_READ
] =
1130 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] =
1131 DriverObject
->MajorFunction
[IRP_MJ_QUERY_INFORMATION
] =
1132 DriverObject
->MajorFunction
[IRP_MJ_SET_INFORMATION
] =
1133 DriverObject
->MajorFunction
[IRP_MJ_QUERY_VOLUME_INFORMATION
] =
1134 DriverObject
->MajorFunction
[IRP_MJ_FILE_SYSTEM_CONTROL
] =
1135 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = (PDRIVER_DISPATCH
)RawDispatch
;
1137 /* Shutdown and unload */
1138 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = RawShutdown
;
1139 DriverObject
->DriverUnload
= RawUnload
;
1141 /* Register the file systems */
1142 IoRegisterFileSystem(RawDiskDeviceObject
);
1143 IoRegisterFileSystem(RawCdromDeviceObject
);
1144 IoRegisterFileSystem(RawTapeDeviceObject
);
1146 #if 0 // FIXME: DriverUnload is never called
1147 /* Reference device objects */
1148 ObReferenceObject(RawDiskDeviceObject
);
1149 ObReferenceObject(RawCdromDeviceObject
);
1150 ObReferenceObject(RawTapeDeviceObject
);
1152 return STATUS_SUCCESS
;