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 *******************************************************************/
25 #include <reactos/drivers/ntddrdsk.h>
30 /* GLOBALS ********************************************************************/
32 typedef enum _RAMDISK_DEVICE_TYPE
36 } RAMDISK_DEVICE_TYPE
;
38 typedef enum _RAMDISK_DEVICE_STATE
40 RamdiskStateUninitialized
,
45 RamdiskStateBusRemoved
,
46 RamdiskStateEnumerated
,
47 } RAMDISK_DEVICE_STATE
;
49 DEFINE_GUID(RamdiskBusInterface
,
53 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
55 typedef struct _RAMDISK_EXTENSION
57 RAMDISK_DEVICE_TYPE Type
;
58 RAMDISK_DEVICE_STATE State
;
59 PDEVICE_OBJECT DeviceObject
;
60 PDEVICE_OBJECT PhysicalDeviceObject
;
61 PDEVICE_OBJECT AttachedDevice
;
62 IO_REMOVE_LOCK RemoveLock
;
63 UNICODE_STRING DriveDeviceName
;
64 UNICODE_STRING BusDeviceName
;
65 FAST_MUTEX DiskListLock
;
67 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
69 typedef struct _RAMDISK_BUS_EXTENSION
72 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
74 typedef struct _RAMDISK_DRIVE_EXTENSION
78 UNICODE_STRING GuidString
;
79 UNICODE_STRING SymbolicLinkName
;
81 RAMDISK_CREATE_OPTIONS DiskOptions
;
86 ULONG SectorsPerTrack
;
88 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
90 ULONG MaximumViewLength
;
91 ULONG MaximumPerDiskViewLength
;
92 ULONG ReportDetectedDevice
;
93 ULONG MarkRamdisksAsRemovable
;
94 ULONG MinimumViewCount
;
95 ULONG DefaultViewCount
;
96 ULONG MaximumViewCount
;
97 ULONG MinimumViewLength
;
98 ULONG DefaultViewLength
;
99 UNICODE_STRING DriverRegistryPath
;
100 BOOLEAN ExportBootDiskAsCd
;
102 PDEVICE_OBJECT RamdiskBusFdo
;
104 /* FUNCTIONS ******************************************************************/
108 QueryParameters(IN PUNICODE_STRING RegistryPath
)
110 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
111 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
116 MaximumViewLength
= 0x10000000u
;
117 MaximumPerDiskViewLength
= 0x10000000u
;
118 ReportDetectedDevice
= 0;
119 MarkRamdisksAsRemovable
= 0;
120 MinimumViewCount
= 2;
121 DefaultViewCount
= 16;
122 MaximumViewCount
= 64;
123 MinimumViewLength
= 0x10000u
;
124 DefaultViewLength
= 0x100000u
;
127 // Setup the query table and query the registry
129 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
130 QueryTable
[0].Flags
= 1;
131 QueryTable
[0].Name
= L
"Parameters";
132 QueryTable
[1].Flags
= 32;
133 QueryTable
[1].Name
= L
"ReportDetectedDevice";
134 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
135 QueryTable
[2].Flags
= 32;
136 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
137 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
138 QueryTable
[3].Flags
= 32;
139 QueryTable
[3].Name
= L
"MinimumViewCount";
140 QueryTable
[3].EntryContext
= &MinimumViewCount
;
141 QueryTable
[4].Flags
= 32;
142 QueryTable
[4].Name
= L
"DefaultViewCount";
143 QueryTable
[4].EntryContext
= &DefaultViewCount
;
144 QueryTable
[5].Flags
= 32;
145 QueryTable
[5].Name
= L
"MaximumViewCount";
146 QueryTable
[5].EntryContext
= &MaximumViewCount
;
147 QueryTable
[6].Flags
= 32;
148 QueryTable
[6].Name
= L
"MinimumViewLength";
149 QueryTable
[6].EntryContext
= &MinimumViewLength
;
150 QueryTable
[7].Flags
= 32;
151 QueryTable
[7].Name
= L
"DefaultViewLength";
152 QueryTable
[7].EntryContext
= &DefaultViewLength
;
153 QueryTable
[8].Flags
= 32;
154 QueryTable
[8].Name
= L
"MaximumViewLength";
155 QueryTable
[8].EntryContext
= &MaximumViewLength
;
156 QueryTable
[9].Flags
= 32;
157 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
158 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
159 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
160 RegistryPath
->Buffer
,
166 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
168 MinView
= MinimumViewCount
;
169 if (MinimumViewCount
>= 2)
171 if (MinimumViewCount
> 256) MinView
= 256;
177 MinimumViewCount
= MinView
;
180 // Parse default view count, cannot be bigger than 256 or smaller than minimum
182 DefView
= DefaultViewCount
;
183 if (DefaultViewCount
>= MinView
)
185 if (DefaultViewCount
> 256) DefView
= 256;
191 DefaultViewCount
= DefView
;
194 // Parse maximum view count, cannot be bigger than 256 or smaller than default
196 if (MaximumViewCount
>= DefView
)
198 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
202 MaximumViewCount
= DefView
;
206 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
208 MinViewLength
= MinimumViewLength
;
209 if (MinimumViewLength
>= 0x10000)
211 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
215 MinViewLength
= 0x10000u
;
217 MinimumViewLength
= MinViewLength
;
220 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
222 DefViewLength
= DefaultViewLength
;
223 if (DefaultViewLength
>= MinViewLength
)
225 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
229 DefViewLength
= MinViewLength
;
231 DefaultViewLength
= DefViewLength
;
234 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
236 MaxViewLength
= MaximumViewLength
;
237 if (MaximumViewLength
>= DefViewLength
)
239 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
243 MaxViewLength
= DefViewLength
;
245 MaximumViewLength
= MaxViewLength
;
248 // Parse maximum view length per disk, cannot be smaller than 16MB
250 if (MaximumPerDiskViewLength
>= 0x1000000)
252 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
256 MaximumPerDiskViewLength
= 0x1000000u
;
262 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
263 IN PRAMDISK_CREATE_INPUT Input
,
264 IN BOOLEAN ValidateOnly
,
265 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
267 ULONG BasePage
, ViewCount
, DiskType
, Length
;
269 PDEVICE_OBJECT DeviceObject
;
270 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
272 WCHAR LocalBuffer
[16];
273 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
276 // Check if we're a CDROM-type RAM disk
278 DiskType
= Input
->DiskType
;
279 if (DiskType
> FILE_DEVICE_CD_ROM
)
282 // Check if we're an ISO
284 if (DiskType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
287 // NTLDR mounted us somewhere
289 BasePage
= Input
->BasePage
;
290 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
293 // Sanitize disk options
295 Input
->Options
.Fixed
= TRUE
;
296 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
297 Input
->Options
.Readonly
;
298 Input
->Options
.Hidden
= FALSE
;
299 Input
->Options
.NoDosDevice
= FALSE
;
300 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
305 // The only other possibility is a controller
307 if (DiskType
!= FILE_DEVICE_CONTROLLER
)
308 return STATUS_INVALID_PARAMETER
;
311 // Read the view count instead
313 ViewCount
= Input
->ViewCount
;
316 // Sanitize disk options
318 Input
->Options
.Hidden
= FALSE
;
319 Input
->Options
.NoDosDevice
= FALSE
;
320 Input
->Options
.Readonly
= FALSE
;
321 Input
->Options
.NoDriveLetter
= TRUE
;
322 Input
->Options
.Fixed
= TRUE
;
326 // Are we just validating and returning to the user?
328 if (ValidateOnly
) return STATUS_SUCCESS
;
331 // Build the GUID string
333 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
334 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
339 Status
= STATUS_INSUFFICIENT_RESOURCES
;
344 // Allocate our device name
346 Length
= GuidString
.Length
+ 32;
347 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
349 TAG('R', 'a', 'm', 'd'));
355 Status
= STATUS_INSUFFICIENT_RESOURCES
;
360 // Build the device name string
362 DeviceName
.Buffer
= Buffer
;
363 DeviceName
.Length
= Length
- 2;
364 DeviceName
.MaximumLength
= Length
;
365 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
366 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
367 DPRINT1("Creating device: %wZ\n", &DeviceName
);
370 // Create the drive device
372 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
373 sizeof(RAMDISK_DRIVE_EXTENSION
),
379 if (!NT_SUCCESS(Status
)) goto FailCreate
;
382 // Grab the drive extension
384 DriveExtension
= DeviceObject
->DeviceExtension
;
387 // Check if we need a DOS device
389 if (!Input
->Options
.NoDosDevice
)
392 // Build the symbolic link name
394 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
395 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
396 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
397 SymbolicLinkName
.MaximumLength
,
398 TAG('R', 'a', 'm', 'd'));
399 SymbolicLinkName
.Buffer
= Buffer
;
406 L
"\\GLOBAL??\\Ramdisk",
407 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
410 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
411 DPRINT1("Creating symbolic link: %wZ to %wZ \n",
412 &SymbolicLinkName
, &DeviceName
);
413 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
414 if (!NT_SUCCESS(Status
))
419 Input
->Options
.NoDosDevice
= TRUE
;
421 SymbolicLinkName
.Buffer
= NULL
;
429 Input
->Options
.NoDosDevice
= TRUE
;
433 // It this an ISO boot ramdisk?
435 if (Input
->DiskType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
438 // Does it need a drive letter?
440 if (!Input
->Options
.NoDriveLetter
)
443 // Build it and take over the existing symbolic link
445 _snwprintf(LocalBuffer
,
447 L
"\\DosDevices\\%wc:",
449 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
450 DPRINT1("Creating symbolic link: %wZ to %wZ\n",
451 &DriveString
, &DeviceName
);
452 IoDeleteSymbolicLink(&DriveString
);
453 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
456 // Save the drive letter
458 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
465 // Setup the device object flags
467 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
468 DeviceObject
->AlignmentRequirement
= 1;
471 // Build the drive FDO
473 *NewDriveExtension
= DriveExtension
;
474 DriveExtension
->Type
= RamdiskDrive
;
475 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
476 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
477 TAG('R', 'a', 'm', 'd'),
480 DriveExtension
->DriveDeviceName
= DeviceName
;
481 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
482 DriveExtension
->GuidString
= GuidString
;
483 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
484 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
485 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
486 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
487 DriveExtension
->DiskType
= Input
->DiskType
;
488 DriveExtension
->DiskOptions
= Input
->Options
;
489 DriveExtension
->DiskLength
= Input
->DiskLength
;
490 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
493 // Make sure we don't free it later
495 DeviceName
.Buffer
= NULL
;
496 SymbolicLinkName
.Buffer
= NULL
;
497 GuidString
.Buffer
= NULL
;
500 // Only support ISO stuff for now
502 ASSERT(Input
->Options
.ExportAsCd
== TRUE
);
503 ASSERT(Input
->DiskType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
);
506 // Setup partition parameters
508 DriveExtension
->BytesPerSector
= 2048; // 512 for Disk
509 DriveExtension
->SectorsPerTrack
= 32; // 128 for disk
510 DriveExtension
->NumberOfHeads
= 64; // 16 for disk
513 // Acquire the disk lock
515 KeEnterCriticalRegion();
516 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
521 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
526 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
527 KeLeaveCriticalRegion();
532 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
533 return STATUS_SUCCESS
;
539 return STATUS_SUCCESS
;
544 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
546 IN BOOLEAN ValidateOnly
)
548 PRAMDISK_CREATE_INPUT Input
;
550 PRAMDISK_BUS_EXTENSION DeviceExtension
;
551 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
553 PWCHAR FileNameStart
, FileNameEnd
;
555 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
558 // Get the device extension and our input data
560 DeviceExtension
= DeviceObject
->DeviceExtension
;
561 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
562 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
565 // Validate input parameters
567 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
568 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
573 return STATUS_INVALID_PARAMETER
;
577 // Validate the disk type
579 DiskType
= Input
->DiskType
;
580 if (DiskType
== FILE_DEVICE_CONTROLLER
) return STATUS_INVALID_PARAMETER
;
583 // Look at the disk type
585 if (DiskType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
588 // We only allow this as an early-init boot
590 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
593 // Save command-line flags
595 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
596 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
600 // Validate the disk type
602 if ((Input
->Options
.ExportAsCd
) &&
603 (DiskType
!= FILE_DEVICE_CD_ROM_FILE_SYSTEM
))
606 // If the type isn't CDFS, it has to at least be raw CD
608 if (DiskType
!= FILE_DEVICE_CD_ROM
) return STATUS_INVALID_PARAMETER
;
612 // Check if this is an actual file
614 if (DiskType
<= FILE_DEVICE_CD_ROM
)
617 // Validate the file name
619 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
620 FileNameEnd
= Input
->FileName
+ 1;
621 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
622 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
626 // Create the actual device
628 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
632 if (NT_SUCCESS(Status
))
635 // Invalidate and set success
637 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
638 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
649 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
652 PRAMDISK_BUS_EXTENSION DeviceExtension
;
654 PIO_STACK_LOCATION IoStackLocation
;
658 // Get the stack location
660 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
663 // Free the work item
665 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
668 // Grab the device extension and lock it
670 DeviceExtension
= DeviceObject
->DeviceExtension
;
671 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
672 if (NT_SUCCESS(Status
))
675 // Discriminate by major code
677 switch (IoStackLocation
->MajorFunction
)
682 case IRP_MJ_DEVICE_CONTROL
:
685 // Let's take a look at the IOCTL
687 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
690 // Ramdisk create request
692 case FSCTL_CREATE_RAM_DISK
:
695 // This time we'll do it for real
697 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
700 case IOCTL_DISK_SET_PARTITION_INFO
:
702 DPRINT1("Set partition info request\n");
707 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
709 DPRINT1("Get drive layout request\n");
714 case IOCTL_DISK_GET_PARTITION_INFO
:
716 DPRINT1("Get partitinon info request\n");
723 DPRINT1("Invalid request\n");
735 // Read or write request
740 DPRINT1("Read/Write request\n");
746 // Internal request (SCSI?)
748 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
750 DPRINT1("SCSI request\n");
758 case IRP_MJ_FLUSH_BUFFERS
:
760 DPRINT1("Flush request\n");
770 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
779 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
780 Irp
->IoStatus
.Status
= Status
;
781 Irp
->IoStatus
.Information
= 0;
782 return IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
788 Irp
->IoStatus
.Status
= Status
;
789 Irp
->IoStatus
.Information
= 0;
790 return IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
795 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
798 PIO_WORKITEM WorkItem
;
801 // Mark the IRP pending
803 IoMarkIrpPending(Irp
);
806 // Allocate a work item
808 WorkItem
= IoAllocateWorkItem(DeviceObject
);
814 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
815 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
816 return STATUS_PENDING
;
823 return STATUS_INSUFFICIENT_RESOURCES
;
829 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
835 Irp
->IoStatus
.Information
= 1;
836 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
837 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
838 return STATUS_SUCCESS
;
843 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
848 return STATUS_SUCCESS
;
853 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
857 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
858 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
862 // Grab the remove lock
864 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
865 if (!NT_SUCCESS(Status
))
870 Irp
->IoStatus
.Information
= 0;
871 Irp
->IoStatus
.Status
= Status
;
872 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
877 // Setup some defaults
879 Status
= STATUS_INVALID_DEVICE_REQUEST
;
883 // Check if this is an bus device or the drive
885 if (DeviceExtension
->Type
== RamdiskBus
)
888 // Check what the request is
890 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
893 // Request to create a ramdisk
895 case FSCTL_CREATE_RAM_DISK
:
900 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
901 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
907 // We don't handle anything else yet
916 // Check what the request is
918 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
920 case IOCTL_DISK_CHECK_VERIFY
:
921 case IOCTL_STORAGE_CHECK_VERIFY
:
922 case IOCTL_STORAGE_CHECK_VERIFY2
:
923 case IOCTL_CDROM_CHECK_VERIFY
:
929 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
930 case IOCTL_DISK_GET_MEDIA_TYPES
:
931 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
932 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
938 case IOCTL_CDROM_READ_TOC
:
944 case IOCTL_DISK_SET_PARTITION_INFO
:
950 case IOCTL_DISK_GET_PARTITION_INFO
:
956 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
962 case IOCTL_DISK_GET_LENGTH_INFO
:
968 case IOCTL_DISK_IS_WRITABLE
:
974 case IOCTL_SCSI_MINIPORT
:
980 case IOCTL_STORAGE_QUERY_PROPERTY
:
986 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
992 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
998 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1004 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1010 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1016 case IOCTL_VOLUME_OFFLINE
:
1025 // Drive code not emulated
1027 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1032 // If requests drop down here, we just return them complete them
1034 goto CompleteRequest
;
1038 // Queue the request to our worker thread
1040 Status
= SendIrpToThread(DeviceObject
, Irp
);
1046 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1047 if (Status
!= STATUS_PENDING
)
1050 // Complete the request
1052 Irp
->IoStatus
.Status
= Status
;
1053 Irp
->IoStatus
.Information
= Information
;
1054 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1065 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1066 IN PDEVICE_OBJECT DeviceObject
,
1069 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1070 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1071 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1072 ULONG Count
, DiskCount
, FinalCount
;
1073 PLIST_ENTRY ListHead
, NextEntry
;
1074 PDEVICE_OBJECT
* DriveDeviceObject
;
1075 RAMDISK_DEVICE_STATE State
;
1078 // Get the device extension and check if this is a drive
1080 DeviceExtension
= DeviceObject
->DeviceExtension
;
1081 if (DeviceExtension
->Type
== RamdiskDrive
)
1091 // Anything but bus relations, we don't handle
1093 if (Type
) goto PassToNext
;
1096 // Acquire the disk list lock
1098 KeEnterCriticalRegion();
1099 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1102 // Did a device already fill relations?
1104 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1105 if (DeviceRelations
)
1110 Count
= DeviceRelations
->Count
;
1121 // Now loop our drives
1124 ListHead
= &DeviceExtension
->DiskList
;
1125 NextEntry
= ListHead
->Flink
;
1126 while (NextEntry
!= ListHead
)
1129 // As long as it wasn't removed, count it in
1131 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1132 RAMDISK_DRIVE_EXTENSION
,
1134 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1137 // Move to the next one
1139 NextEntry
= NextEntry
->Flink
;
1143 // Now we know our final count
1145 FinalCount
= Count
+ DiskCount
;
1148 // Allocate the structure
1150 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1151 FIELD_OFFSET(DEVICE_RELATIONS
,
1154 sizeof(PDEVICE_OBJECT
),
1155 TAG('R', 'a', 'm', 'd'));
1156 if (!OurDeviceRelations
)
1161 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1162 KeLeaveCriticalRegion();
1163 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1164 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1165 return STATUS_INSUFFICIENT_RESOURCES
;
1169 // Check if we already had some relations
1176 RtlCopyMemory(OurDeviceRelations
->Objects
,
1177 DeviceRelations
->Objects
,
1178 Count
* sizeof(PDEVICE_OBJECT
));
1184 OurDeviceRelations
->Count
= FinalCount
;
1187 // Now loop our drives again
1189 ListHead
= &DeviceExtension
->DiskList
;
1190 NextEntry
= ListHead
->Flink
;
1191 while (NextEntry
!= ListHead
)
1194 // Go to the end of the list
1196 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1199 // Get the drive state
1201 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1202 RAMDISK_DRIVE_EXTENSION
,
1204 State
= DriveExtension
->State
;
1207 // If it was removed or enumerated, we don't touch the device object
1209 if (State
>= RamdiskStateBusRemoved
)
1212 // If it was removed, we still have to keep track of this though
1214 if (State
== RamdiskStateBusRemoved
)
1217 // Mark it as enumerated now, but don't actually reference it
1219 DriveExtension
->State
= RamdiskStateEnumerated
;
1225 // First time it's enumerated, reference the device object
1227 ObReferenceObject(DriveExtension
->DeviceObject
);
1230 // Save the object pointer, and move on
1232 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1235 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1238 // Move to the next one
1240 NextEntry
= NextEntry
->Flink
;
1246 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1247 KeLeaveCriticalRegion();
1250 // Cleanup old relations
1252 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1257 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1258 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1261 // Pass to the next driver
1264 IoCopyCurrentIrpStackLocationToNext(Irp
);
1265 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1270 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1273 PIO_STACK_LOCATION IoStackLocation
;
1274 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1279 // Get the device extension and stack location
1281 DeviceExtension
= DeviceObject
->DeviceExtension
;
1282 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1283 Minor
= IoStackLocation
->MinorFunction
;
1286 // Check if the bus is removed
1288 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1291 // Only remove-device and query-id are allowed
1293 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
1296 // Fail anything else
1298 Status
= STATUS_NO_SUCH_DEVICE
;
1299 Irp
->IoStatus
.Status
= Status
;
1300 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1306 // Acquire the remove lock
1308 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1309 if (!NT_SUCCESS(Status
))
1314 Irp
->IoStatus
.Information
= 0;
1315 Irp
->IoStatus
.Status
= Status
;
1316 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1321 // Query the IRP type
1325 case IRP_MN_START_DEVICE
:
1327 DPRINT1("PnP IRP: %lx\n", Minor
);
1331 case IRP_MN_QUERY_STOP_DEVICE
:
1333 DPRINT1("PnP IRP: %lx\n", Minor
);
1337 case IRP_MN_CANCEL_STOP_DEVICE
:
1339 DPRINT1("PnP IRP: %lx\n", Minor
);
1343 case IRP_MN_STOP_DEVICE
:
1345 DPRINT1("PnP IRP: %lx\n", Minor
);
1349 case IRP_MN_QUERY_REMOVE_DEVICE
:
1351 DPRINT1("PnP IRP: %lx\n", Minor
);
1355 case IRP_MN_CANCEL_REMOVE_DEVICE
:
1357 DPRINT1("PnP IRP: %lx\n", Minor
);
1361 case IRP_MN_REMOVE_DEVICE
:
1363 DPRINT1("PnP IRP: %lx\n", Minor
);
1367 case IRP_MN_SURPRISE_REMOVAL
:
1369 DPRINT1("PnP IRP: %lx\n", Minor
);
1373 case IRP_MN_QUERY_ID
:
1378 if (DeviceExtension
->Type
== RamdiskDrive
)
1380 DPRINT1("PnP IRP: %lx\n", Minor
);
1385 case IRP_MN_QUERY_BUS_INFORMATION
:
1390 if (DeviceExtension
->Type
== RamdiskDrive
)
1392 DPRINT1("PnP IRP: %lx\n", Minor
);
1399 DPRINT1("PnP IRP: %lx\n", Minor
);
1403 case IRP_MN_QUERY_DEVICE_TEXT
:
1408 if (DeviceExtension
->Type
== RamdiskDrive
)
1410 DPRINT1("PnP IRP: %lx\n", Minor
);
1415 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1418 // Call our main routine
1420 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
1422 QueryDeviceRelations
.Type
,
1425 goto ReleaseAndReturn
;
1427 case IRP_MN_QUERY_CAPABILITIES
:
1432 if (DeviceExtension
->Type
== RamdiskDrive
)
1434 DPRINT1("PnP IRP: %lx\n", Minor
);
1439 case IRP_MN_QUERY_RESOURCES
:
1440 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
1443 // Complete immediately without touching it
1445 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1446 goto ReleaseAndReturn
;
1450 DPRINT1("Illegal IRP: %lx\n", Minor
);
1457 if (DeviceExtension
->Type
== RamdiskBus
)
1460 // Do we have an attached device?
1462 if (DeviceExtension
->AttachedDevice
)
1467 IoSkipCurrentIrpStackLocation(Irp
);
1468 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1473 // Release the lock and return status
1476 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1482 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
1487 return STATUS_SUCCESS
;
1492 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
1497 return STATUS_SUCCESS
;
1502 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
1507 return STATUS_SUCCESS
;
1512 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
1517 return STATUS_SUCCESS
;
1522 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
1530 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
1531 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1533 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1534 PDEVICE_OBJECT AttachedDevice
;
1536 UNICODE_STRING DeviceName
;
1537 PDEVICE_OBJECT DeviceObject
;
1540 // Only create the bus FDO once
1542 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
1545 // Create the bus FDO
1547 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
1548 Status
= IoCreateDevice(DriverObject
,
1549 sizeof(RAMDISK_BUS_EXTENSION
),
1551 FILE_DEVICE_BUS_EXTENDER
,
1552 FILE_DEVICE_SECURE_OPEN
,
1555 if (NT_SUCCESS(Status
))
1558 // Initialize the bus FDO extension
1560 DeviceExtension
= DeviceObject
->DeviceExtension
;
1561 RtlZeroMemory(DeviceObject
->DeviceExtension
,
1562 sizeof(RAMDISK_BUS_EXTENSION
));
1565 // Set bus FDO flags
1567 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
1570 // Setup the bus FDO extension
1572 DeviceExtension
->Type
= RamdiskBus
;
1573 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
1574 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
1575 TAG('R', 'a', 'm', 'd'),
1578 InitializeListHead(&DeviceExtension
->DiskList
);
1579 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1580 DeviceExtension
->DeviceObject
= DeviceObject
;
1583 // Register the RAM disk device interface
1585 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
1586 &RamdiskBusInterface
,
1588 &DeviceExtension
->BusDeviceName
);
1589 if (!NT_SUCCESS(Status
))
1594 IoDeleteDevice(DeviceObject
);
1599 // Attach us to the device stack
1601 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
1602 PhysicalDeviceObject
);
1603 DeviceExtension
->AttachedDevice
= AttachedDevice
;
1604 if (!AttachedDevice
)
1609 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
1610 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
1611 IoDeleteDevice(DeviceObject
);
1612 return STATUS_NO_SUCH_DEVICE
;
1616 // Bus FDO is initialized
1618 RamdiskBusFdo
= DeviceObject
;
1621 // Loop for loader block
1626 // Are we being booted from setup? Not yet supported
1628 ASSERT (!KeLoaderBlock
->SetupLdrBlock
);
1634 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
1635 Status
= STATUS_SUCCESS
;
1646 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
1647 IN PUNICODE_STRING RegistryPath
)
1649 PCHAR BootDeviceName
, CommandLine
;
1650 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
1654 // Query ramdisk parameters
1656 QueryParameters(RegistryPath
);
1659 // Save the registry path
1661 DriverRegistryPath
= *RegistryPath
;
1662 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
1663 RegistryPath
->Length
+
1665 TAG('R', 'a', 'm', 'd'));
1666 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1667 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
1670 // Set device routines
1672 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
1673 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
1674 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
1675 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
1676 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
1677 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
1678 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
1679 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
1680 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
1681 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
1682 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
1683 DriverObject
->DriverUnload
= RamdiskUnload
;
1686 // Check for a loader block
1691 // Get the boot device name
1693 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
1697 // Check if we're booting from ramdisk
1699 if ((strlen(BootDeviceName
) >= 10) &&
1700 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
1703 // We'll have to tell the PnP Manager
1705 ReportDetectedDevice
= TRUE
;
1708 // Check for a command line
1710 CommandLine
= KeLoaderBlock
->LoadOptions
;
1714 // Check if this is an ISO boot
1716 if (strstr(CommandLine
, "RDEXPORTASCD"))
1719 // Remember for later
1721 ExportBootDiskAsCd
= TRUE
;
1725 // Check if this is PE boot
1727 if (strstr(CommandLine
, "MININT"))
1730 // Remember for later
1741 // Installing from Ramdisk isn't supported yet
1743 ASSERT(!KeLoaderBlock
->SetupLdrBlock
);
1746 // Are we reporting the device
1748 if (ReportDetectedDevice
)
1753 Status
= IoReportDetectedDevice(DriverObject
,
1754 InterfaceTypeUndefined
,
1760 &PhysicalDeviceObject
);
1761 if (NT_SUCCESS(Status
))
1765 // The ReactOS Plug and Play Manager is broken and does not create
1766 // the required keys when reporting a detected device.
1767 // We hack around this ourselves.
1769 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
1770 PhysicalDeviceObject
->DeviceObjectExtension
)
1771 ->DeviceNode
->InstancePath
,
1772 L
"Root\\UNKNOWN\\0000");
1775 // Create the device object
1777 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
1778 if (NT_SUCCESS(Status
))
1783 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1784 Status
= STATUS_SUCCESS
;
1793 Status
= STATUS_SUCCESS
;