2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
23 #include <reactos/drivers/ntddrdsk.h>
27 /* GLOBALS ********************************************************************/
29 typedef enum _RAMDISK_DEVICE_TYPE
33 } RAMDISK_DEVICE_TYPE
;
35 typedef enum _RAMDISK_DEVICE_STATE
37 RamdiskStateUninitialized
,
42 RamdiskStateBusRemoved
,
43 } RAMDISK_DEVICE_STATE
;
45 DEFINE_GUID(RamdiskBusInterface
,
49 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
51 typedef struct _RAMDISK_EXTENSION
53 RAMDISK_DEVICE_TYPE Type
;
54 RAMDISK_DEVICE_STATE State
;
55 PDEVICE_OBJECT DeviceObject
;
56 PDEVICE_OBJECT PhysicalDeviceObject
;
57 PDEVICE_OBJECT AttachedDevice
;
58 IO_REMOVE_LOCK RemoveLock
;
59 UNICODE_STRING SymbolicLinkName
;
60 FAST_MUTEX DiskListLock
;
61 LIST_ENTRY DiskListHead
;
62 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
64 ULONG MaximumViewLength
;
65 ULONG MaximumPerDiskViewLength
;
66 ULONG ReportDetectedDevice
;
67 ULONG MarkRamdisksAsRemovable
;
68 ULONG MinimumViewCount
;
69 ULONG DefaultViewCount
;
70 ULONG MaximumViewCount
;
71 ULONG MinimumViewLength
;
72 ULONG DefaultViewLength
;
73 UNICODE_STRING DriverRegistryPath
;
74 BOOLEAN ExportBootDiskAsCd
;
76 PDEVICE_OBJECT RamdiskBusFdo
;
78 /* FUNCTIONS ******************************************************************/
82 QueryParameters(IN PUNICODE_STRING RegistryPath
)
84 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
85 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
90 MaximumViewLength
= 0x10000000u
;
91 MaximumPerDiskViewLength
= 0x10000000u
;
92 ReportDetectedDevice
= 0;
93 MarkRamdisksAsRemovable
= 0;
95 DefaultViewCount
= 16;
96 MaximumViewCount
= 64;
97 MinimumViewLength
= 0x10000u
;
98 DefaultViewLength
= 0x100000u
;
101 // Setup the query table and query the registry
103 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
104 QueryTable
[0].Flags
= 1;
105 QueryTable
[0].Name
= L
"Parameters";
106 QueryTable
[1].Flags
= 32;
107 QueryTable
[1].Name
= L
"ReportDetectedDevice";
108 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
109 QueryTable
[2].Flags
= 32;
110 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
111 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
112 QueryTable
[3].Flags
= 32;
113 QueryTable
[3].Name
= L
"MinimumViewCount";
114 QueryTable
[3].EntryContext
= &MinimumViewCount
;
115 QueryTable
[4].Flags
= 32;
116 QueryTable
[4].Name
= L
"DefaultViewCount";
117 QueryTable
[4].EntryContext
= &DefaultViewCount
;
118 QueryTable
[5].Flags
= 32;
119 QueryTable
[5].Name
= L
"MaximumViewCount";
120 QueryTable
[5].EntryContext
= &MaximumViewCount
;
121 QueryTable
[6].Flags
= 32;
122 QueryTable
[6].Name
= L
"MinimumViewLength";
123 QueryTable
[6].EntryContext
= &MinimumViewLength
;
124 QueryTable
[7].Flags
= 32;
125 QueryTable
[7].Name
= L
"DefaultViewLength";
126 QueryTable
[7].EntryContext
= &DefaultViewLength
;
127 QueryTable
[8].Flags
= 32;
128 QueryTable
[8].Name
= L
"MaximumViewLength";
129 QueryTable
[8].EntryContext
= &MaximumViewLength
;
130 QueryTable
[9].Flags
= 32;
131 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
132 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
133 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
134 RegistryPath
->Buffer
,
140 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
142 MinView
= MinimumViewCount
;
143 if (MinimumViewCount
>= 2)
145 if (MinimumViewCount
> 256) MinView
= 256;
151 MinimumViewCount
= MinView
;
154 // Parse default view count, cannot be bigger than 256 or smaller than minimum
156 DefView
= DefaultViewCount
;
157 if (DefaultViewCount
>= MinView
)
159 if (DefaultViewCount
> 256) DefView
= 256;
165 DefaultViewCount
= DefView
;
168 // Parse maximum view count, cannot be bigger than 256 or smaller than default
170 if (MaximumViewCount
>= DefView
)
172 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
176 MaximumViewCount
= DefView
;
180 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
182 MinViewLength
= MinimumViewLength
;
183 if (MinimumViewLength
>= 0x10000)
185 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
189 MinViewLength
= 0x10000u
;
191 MinimumViewLength
= MinViewLength
;
194 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
196 DefViewLength
= DefaultViewLength
;
197 if (DefaultViewLength
>= MinViewLength
)
199 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
203 DefViewLength
= MinViewLength
;
205 DefaultViewLength
= DefViewLength
;
208 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
210 MaxViewLength
= MaximumViewLength
;
211 if (MaximumViewLength
>= DefViewLength
)
213 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
217 MaxViewLength
= DefViewLength
;
219 MaximumViewLength
= MaxViewLength
;
222 // Parse maximum view length per disk, cannot be smaller than 16MB
224 if (MaximumPerDiskViewLength
>= 0x1000000)
226 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
230 MaximumPerDiskViewLength
= 0x1000000u
;
236 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
242 Irp
->IoStatus
.Information
= 1;
243 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
244 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
245 return STATUS_SUCCESS
;
250 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
255 return STATUS_SUCCESS
;
260 RamdiskCreateDiskDevice(IN PRAMDISK_EXTENSION DeviceExtension
,
261 IN PRAMDISK_CREATE_INPUT Input
,
262 IN BOOLEAN ValidateOnly
,
263 OUT PDEVICE_OBJECT
*DeviceObject
)
267 return STATUS_SUCCESS
;
272 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
274 IN BOOLEAN ValidateOnly
)
276 PRAMDISK_CREATE_INPUT Input
;
278 PRAMDISK_EXTENSION DeviceExtension
;
280 PWCHAR FileNameStart
, FileNameEnd
;
282 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
285 // Get the device extension and our input data
287 DeviceExtension
= (PRAMDISK_EXTENSION
)DeviceObject
->DeviceExtension
;
288 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
289 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
292 // Validate input parameters
294 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
295 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
300 return STATUS_INVALID_PARAMETER
;
304 // Validate the disk type
306 DiskType
= Input
->DiskType
;
307 if (DiskType
== FILE_DEVICE_CONTROLLER
) return STATUS_INVALID_PARAMETER
;
310 // Look at the disk type
312 if (DiskType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
315 // We only allow this as an early-init boot
317 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
320 // Save command-line flags
322 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
323 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
327 // Validate the disk type
329 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
))
332 // If the type isn't CDFS, it has to at least be raw CD
334 if (DiskType
!= FILE_DEVICE_CD_ROM
) return STATUS_INVALID_PARAMETER
;
338 // Check if this is an actual file
340 if (DiskType
<= FILE_DEVICE_CD_ROM
)
343 // Validate the file name
345 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
346 FileNameEnd
= Input
->FileName
+ 1;
347 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
348 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
352 // Create the actual device
354 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
358 if (NT_SUCCESS(Status
))
361 // Invalidate and set success
363 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
364 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
375 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
379 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
380 PRAMDISK_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
381 ULONG Information
= 0;
384 // Grab the remove lock
386 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
387 if (!NT_SUCCESS(Status
))
392 Irp
->IoStatus
.Information
= 0;
393 Irp
->IoStatus
.Status
= Status
;
394 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
399 // Check if this is an FDO or PDO
401 if (DeviceExtension
->Type
== RamdiskFdo
)
404 // Check what the request is
406 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
409 // Request to create a ramdisk
411 case FSCTL_CREATE_RAM_DISK
:
416 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
417 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
423 // We don't handle anything else yet
432 // PDO code not yet done
438 // Queue the request to our worker thread
447 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
448 if (Status
!= STATUS_PENDING
)
451 // Complete the request
453 Irp
->IoStatus
.Status
= Status
;
454 Irp
->IoStatus
.Information
= Information
;
455 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
466 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
469 PIO_STACK_LOCATION IoStackLocation
;
470 PRAMDISK_EXTENSION DeviceExtension
;
475 // Get the device extension and stack location
477 DeviceExtension
= DeviceObject
->DeviceExtension
;
478 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
479 Minor
= IoStackLocation
->MinorFunction
;
482 // Check if the bus is removed
484 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
487 // Only remove-device and query-id are allowed
489 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
492 // Fail anything else
494 Status
= STATUS_NO_SUCH_DEVICE
;
495 Irp
->IoStatus
.Status
= Status
;
496 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
502 // Acquire the remove lock
504 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
505 if (!NT_SUCCESS(Status
))
510 Irp
->IoStatus
.Information
= 0;
511 Irp
->IoStatus
.Status
= Status
;
512 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
517 // Query the IRP type
521 case IRP_MN_START_DEVICE
:
523 DPRINT1("PnP IRP: %lx\n", Minor
);
527 case IRP_MN_QUERY_STOP_DEVICE
:
529 DPRINT1("PnP IRP: %lx\n", Minor
);
533 case IRP_MN_CANCEL_STOP_DEVICE
:
535 DPRINT1("PnP IRP: %lx\n", Minor
);
539 case IRP_MN_STOP_DEVICE
:
541 DPRINT1("PnP IRP: %lx\n", Minor
);
545 case IRP_MN_QUERY_REMOVE_DEVICE
:
547 DPRINT1("PnP IRP: %lx\n", Minor
);
551 case IRP_MN_CANCEL_REMOVE_DEVICE
:
553 DPRINT1("PnP IRP: %lx\n", Minor
);
557 case IRP_MN_REMOVE_DEVICE
:
559 DPRINT1("PnP IRP: %lx\n", Minor
);
563 case IRP_MN_SURPRISE_REMOVAL
:
565 DPRINT1("PnP IRP: %lx\n", Minor
);
569 case IRP_MN_QUERY_ID
:
574 if (DeviceExtension
->Type
== RamdiskPdo
)
576 DPRINT1("PnP IRP: %lx\n", Minor
);
581 case IRP_MN_QUERY_BUS_INFORMATION
:
586 if (DeviceExtension
->Type
== RamdiskPdo
)
588 DPRINT1("PnP IRP: %lx\n", Minor
);
595 DPRINT1("PnP IRP: %lx\n", Minor
);
599 case IRP_MN_QUERY_DEVICE_TEXT
:
604 if (DeviceExtension
->Type
== RamdiskPdo
)
606 DPRINT1("PnP IRP: %lx\n", Minor
);
611 case IRP_MN_QUERY_DEVICE_RELATIONS
:
613 DPRINT1("PnP IRP: %lx\n", Minor
);
617 case IRP_MN_QUERY_CAPABILITIES
:
622 if (DeviceExtension
->Type
== RamdiskPdo
)
624 DPRINT1("PnP IRP: %lx\n", Minor
);
629 case IRP_MN_QUERY_RESOURCES
:
630 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
633 // Complete immediately without touching it
635 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
636 goto ReleaseAndReturn
;
640 DPRINT1("Illegal IRP: %lx\n", Minor
);
647 if (DeviceExtension
->Type
== RamdiskFdo
)
650 // Do we have an attached device?
652 if (DeviceExtension
->AttachedDevice
)
657 IoSkipCurrentIrpStackLocation(Irp
);
658 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
663 // Release the lock and return status
666 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
672 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
677 return STATUS_SUCCESS
;
682 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
687 return STATUS_SUCCESS
;
692 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
697 return STATUS_SUCCESS
;
702 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
707 return STATUS_SUCCESS
;
712 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
720 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
721 IN PDEVICE_OBJECT PhysicalDeviceObject
)
723 PRAMDISK_EXTENSION DeviceExtension
;
724 PDEVICE_OBJECT AttachedDevice
;
726 UNICODE_STRING DeviceName
;
727 PDEVICE_OBJECT DeviceObject
;
730 // Only create the FDO once
732 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
737 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
738 Status
= IoCreateDevice(DriverObject
,
739 sizeof(RAMDISK_EXTENSION
),
741 FILE_DEVICE_BUS_EXTENDER
,
742 FILE_DEVICE_SECURE_OPEN
,
745 if (NT_SUCCESS(Status
))
748 // Initialize the FDO extension
750 DeviceExtension
= (PRAMDISK_EXTENSION
)DeviceObject
->DeviceExtension
;
751 RtlZeroMemory(DeviceObject
->DeviceExtension
, sizeof(RAMDISK_EXTENSION
));
756 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
759 // Setup the FDO extension
761 DeviceExtension
->Type
= RamdiskFdo
;
762 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
763 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
764 TAG('R', 'a', 'm', 'd'),
767 InitializeListHead(&DeviceExtension
->DiskListHead
);
768 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
769 DeviceExtension
->DeviceObject
= DeviceObject
;
772 // Register the RAM disk device interface
774 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
775 &RamdiskBusInterface
,
777 &DeviceExtension
->SymbolicLinkName
);
778 if (!NT_SUCCESS(Status
))
783 IoDeleteDevice(DeviceObject
);
788 // Attach us to the device stack
790 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
791 PhysicalDeviceObject
);
792 DeviceExtension
->AttachedDevice
= AttachedDevice
;
798 IoSetDeviceInterfaceState(&DeviceExtension
->SymbolicLinkName
, 0);
799 RtlFreeUnicodeString(&DeviceExtension
->SymbolicLinkName
);
800 IoDeleteDevice(DeviceObject
);
801 return STATUS_NO_SUCH_DEVICE
;
805 // FDO is initialized
807 RamdiskBusFdo
= DeviceObject
;
810 // Loop for loader block
815 // Are we being booted from setup? Not yet supported
817 ASSERT (!KeLoaderBlock
->SetupLdrBlock
);
823 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
824 Status
= STATUS_SUCCESS
;
835 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
836 IN PUNICODE_STRING RegistryPath
)
838 PCHAR BootDeviceName
, CommandLine
;
839 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
843 // Query ramdisk parameters
845 QueryParameters(RegistryPath
);
848 // Save the registry path
850 DriverRegistryPath
= *RegistryPath
;
851 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
852 RegistryPath
->Length
+
854 TAG('R', 'a', 'm', 'd'));
855 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
856 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
859 // Set device routines
861 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
862 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
863 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
864 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
865 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
866 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
867 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
868 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
869 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
870 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
871 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
872 DriverObject
->DriverUnload
= RamdiskUnload
;
875 // Check for a loader block
880 // Get the boot device name
882 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
886 // Check if we're booting from ramdisk
888 if ((strlen(BootDeviceName
) >= 10) &&
889 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
892 // We'll have to tell the PnP Manager
894 ReportDetectedDevice
= TRUE
;
897 // Check for a command line
899 CommandLine
= KeLoaderBlock
->LoadOptions
;
903 // Check if this is an ISO boot
905 if (strstr(CommandLine
, "RDEXPORTASCD"))
908 // Remember for later
910 ExportBootDiskAsCd
= TRUE
;
914 // Check if this is PE boot
916 if (strstr(CommandLine
, "MININT"))
919 // Remember for later
930 // Installing from Ramdisk isn't supported yet
932 ASSERT(!KeLoaderBlock
->SetupLdrBlock
);
935 // Are we reporting the device
937 if (ReportDetectedDevice
)
942 Status
= IoReportDetectedDevice(DriverObject
,
943 InterfaceTypeUndefined
,
949 &PhysicalDeviceObject
);
950 if (NT_SUCCESS(Status
))
954 // The ReactOS Plug and Play Manager is broken and does not create
955 // the required keys when reporting a detected device.
956 // We hack around this ourselves.
958 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)PhysicalDeviceObject
->DeviceObjectExtension
)->DeviceNode
->InstancePath
,
959 L
"Root\\UNKNOWN\\0000");
962 // Create the device object
964 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
965 if (NT_SUCCESS(Status
))
970 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
971 Status
= STATUS_SUCCESS
;
980 Status
= STATUS_SUCCESS
;