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>
26 #include "../../../filesystems/fs_rec/fs_rec.h"
31 /* GLOBALS ********************************************************************/
33 #define RAMDISK_SESSION_SIZE \
34 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
36 #define RAMDISK_TOC_SIZE \
37 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
39 #define TOC_DATA_TRACK (0x04)
41 typedef enum _RAMDISK_DEVICE_TYPE
45 } RAMDISK_DEVICE_TYPE
;
47 typedef enum _RAMDISK_DEVICE_STATE
49 RamdiskStateUninitialized
,
54 RamdiskStateBusRemoved
,
55 RamdiskStateEnumerated
,
56 } RAMDISK_DEVICE_STATE
;
58 DEFINE_GUID(RamdiskBusInterface
,
62 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
64 typedef struct _RAMDISK_EXTENSION
66 RAMDISK_DEVICE_TYPE Type
;
67 RAMDISK_DEVICE_STATE State
;
68 PDEVICE_OBJECT DeviceObject
;
69 PDEVICE_OBJECT PhysicalDeviceObject
;
70 PDEVICE_OBJECT AttachedDevice
;
71 IO_REMOVE_LOCK RemoveLock
;
72 UNICODE_STRING DriveDeviceName
;
73 UNICODE_STRING BusDeviceName
;
74 FAST_MUTEX DiskListLock
;
76 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
78 typedef struct _RAMDISK_BUS_EXTENSION
81 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
83 typedef struct _RAMDISK_DRIVE_EXTENSION
87 UNICODE_STRING GuidString
;
88 UNICODE_STRING SymbolicLinkName
;
90 RAMDISK_CREATE_OPTIONS DiskOptions
;
95 ULONG SectorsPerTrack
;
98 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
100 ULONG MaximumViewLength
;
101 ULONG MaximumPerDiskViewLength
;
102 ULONG ReportDetectedDevice
;
103 ULONG MarkRamdisksAsRemovable
;
104 ULONG MinimumViewCount
;
105 ULONG DefaultViewCount
;
106 ULONG MaximumViewCount
;
107 ULONG MinimumViewLength
;
108 ULONG DefaultViewLength
;
109 UNICODE_STRING DriverRegistryPath
;
110 BOOLEAN ExportBootDiskAsCd
;
112 PDEVICE_OBJECT RamdiskBusFdo
;
114 /* FUNCTIONS ******************************************************************/
118 QueryParameters(IN PUNICODE_STRING RegistryPath
)
120 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
121 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
126 MaximumViewLength
= 0x10000000u
;
127 MaximumPerDiskViewLength
= 0x10000000u
;
128 ReportDetectedDevice
= 0;
129 MarkRamdisksAsRemovable
= 0;
130 MinimumViewCount
= 2;
131 DefaultViewCount
= 16;
132 MaximumViewCount
= 64;
133 MinimumViewLength
= 0x10000u
;
134 DefaultViewLength
= 0x100000u
;
137 // Setup the query table and query the registry
139 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
140 QueryTable
[0].Flags
= 1;
141 QueryTable
[0].Name
= L
"Parameters";
142 QueryTable
[1].Flags
= 32;
143 QueryTable
[1].Name
= L
"ReportDetectedDevice";
144 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
145 QueryTable
[2].Flags
= 32;
146 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
147 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
148 QueryTable
[3].Flags
= 32;
149 QueryTable
[3].Name
= L
"MinimumViewCount";
150 QueryTable
[3].EntryContext
= &MinimumViewCount
;
151 QueryTable
[4].Flags
= 32;
152 QueryTable
[4].Name
= L
"DefaultViewCount";
153 QueryTable
[4].EntryContext
= &DefaultViewCount
;
154 QueryTable
[5].Flags
= 32;
155 QueryTable
[5].Name
= L
"MaximumViewCount";
156 QueryTable
[5].EntryContext
= &MaximumViewCount
;
157 QueryTable
[6].Flags
= 32;
158 QueryTable
[6].Name
= L
"MinimumViewLength";
159 QueryTable
[6].EntryContext
= &MinimumViewLength
;
160 QueryTable
[7].Flags
= 32;
161 QueryTable
[7].Name
= L
"DefaultViewLength";
162 QueryTable
[7].EntryContext
= &DefaultViewLength
;
163 QueryTable
[8].Flags
= 32;
164 QueryTable
[8].Name
= L
"MaximumViewLength";
165 QueryTable
[8].EntryContext
= &MaximumViewLength
;
166 QueryTable
[9].Flags
= 32;
167 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
168 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
169 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
170 RegistryPath
->Buffer
,
176 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
178 MinView
= MinimumViewCount
;
179 if (MinimumViewCount
>= 2)
181 if (MinimumViewCount
> 256) MinView
= 256;
187 MinimumViewCount
= MinView
;
190 // Parse default view count, cannot be bigger than 256 or smaller than minimum
192 DefView
= DefaultViewCount
;
193 if (DefaultViewCount
>= MinView
)
195 if (DefaultViewCount
> 256) DefView
= 256;
201 DefaultViewCount
= DefView
;
204 // Parse maximum view count, cannot be bigger than 256 or smaller than default
206 if (MaximumViewCount
>= DefView
)
208 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
212 MaximumViewCount
= DefView
;
216 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
218 MinViewLength
= MinimumViewLength
;
219 if (MinimumViewLength
>= 0x10000)
221 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
225 MinViewLength
= 0x10000u
;
227 MinimumViewLength
= MinViewLength
;
230 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
232 DefViewLength
= DefaultViewLength
;
233 if (DefaultViewLength
>= MinViewLength
)
235 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
239 DefViewLength
= MinViewLength
;
241 DefaultViewLength
= DefViewLength
;
244 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
246 MaxViewLength
= MaximumViewLength
;
247 if (MaximumViewLength
>= DefViewLength
)
249 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
253 MaxViewLength
= DefViewLength
;
255 MaximumViewLength
= MaxViewLength
;
258 // Parse maximum view length per disk, cannot be smaller than 16MB
260 if (MaximumPerDiskViewLength
>= 0x1000000)
262 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
266 MaximumPerDiskViewLength
= 0x1000000u
;
272 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
273 IN LARGE_INTEGER Offset
,
275 OUT PULONG OutputLength
)
277 PHYSICAL_ADDRESS PhysicalAddress
;
281 LARGE_INTEGER ActualOffset
;
282 LARGE_INTEGER ActualPages
;
285 // We only support boot disks for now
287 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
290 // Calculate the actual offset in the drive
292 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
293 DPRINT1("Disk offset is: %d and Offset is: %I64d. Total: %I64d\n",
294 DeviceExtension
->DiskOffset
, Offset
, ActualOffset
);
299 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
300 DPRINT1("Offset in pages is: %I64x\n", ActualPages
);
303 // Now add the base page
305 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
306 DPRINT1("Ramdisk mapped at page: %d, actual page is: %I64d\n",
307 DeviceExtension
->BasePage
, ActualPages
);
310 // Calculate final amount of bytes
312 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
313 DPRINT1("Physical Address is: %I64x\n", PhysicalAddress
);
316 // Calculate pages spanned for the mapping
318 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
319 DPRINT1("Length in pages: %d\n", ActualLength
);
322 // And convert this back to bytes
324 ActualLength
<<= PAGE_SHIFT
;
325 DPRINT1("Length in bytes: %d\n", ActualLength
);
328 // Get the offset within the page
330 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
331 DPRINT1("Page offset: %lx\n", PageOffset
);
334 // Map the I/O Space from the loader
336 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
339 // Return actual offset within the page as well as the length
341 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
342 *OutputLength
= Length
;
343 DPRINT1("Mapped at: %p\n", MappedBase
);
349 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
350 IN PVOID BaseAddress
,
351 IN LARGE_INTEGER Offset
,
354 LARGE_INTEGER ActualOffset
;
359 // We only support boot disks for now
361 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
364 // Calculate the actual offset in the drive
366 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
367 DPRINT1("Disk offset is: %d and Offset is: %I64d. Total: %I64d\n",
368 DeviceExtension
->DiskOffset
, Offset
, ActualOffset
);
371 // Calculate pages spanned for the mapping
373 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
374 DPRINT1("Length in pages: %d\n", ActualLength
);
377 // And convert this back to bytes
379 ActualLength
<<= PAGE_SHIFT
;
380 DPRINT1("Length in bytes: %d\n", ActualLength
);
383 // Get the offset within the page
385 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
386 DPRINT1("Page offset: %lx\n", PageOffset
);
389 // Calculate actual base address where we mapped this
391 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
392 DPRINT1("Unmapping at: %p\n", BaseAddress
);
395 // Unmap the I/O space we got from the loader
397 MmUnmapIoSpace(BaseAddress
, ActualLength
);
402 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
403 IN PRAMDISK_CREATE_INPUT Input
,
404 IN BOOLEAN ValidateOnly
,
405 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
407 ULONG BasePage
, ViewCount
, DiskType
, Length
;
409 PDEVICE_OBJECT DeviceObject
;
410 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
412 WCHAR LocalBuffer
[16];
413 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
414 PPACKED_BOOT_SECTOR BootSector
;
415 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
417 LARGE_INTEGER CurrentOffset
;
420 // Check if we're a boot RAM disk
422 DiskType
= Input
->DiskType
;
423 if (DiskType
>= RAMDISK_BOOT_DISK
)
426 // Check if we're an ISO
428 if (DiskType
== RAMDISK_BOOT_DISK
)
431 // NTLDR mounted us somewhere
433 BasePage
= Input
->BasePage
;
434 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
437 // Sanitize disk options
439 Input
->Options
.Fixed
= TRUE
;
440 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
441 Input
->Options
.Readonly
;
442 Input
->Options
.Hidden
= FALSE
;
443 Input
->Options
.NoDosDevice
= FALSE
;
444 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
449 // The only other possibility is a WIM disk
451 if (DiskType
!= RAMDISK_WIM_DISK
)
456 return STATUS_INVALID_PARAMETER
;
460 // Read the view count instead
462 ViewCount
= Input
->ViewCount
;
465 // Sanitize disk options
467 Input
->Options
.Hidden
= FALSE
;
468 Input
->Options
.NoDosDevice
= FALSE
;
469 Input
->Options
.Readonly
= FALSE
;
470 Input
->Options
.NoDriveLetter
= TRUE
;
471 Input
->Options
.Fixed
= TRUE
;
475 // Are we just validating and returning to the user?
477 if (ValidateOnly
) return STATUS_SUCCESS
;
480 // Build the GUID string
482 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
483 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
488 Status
= STATUS_INSUFFICIENT_RESOURCES
;
493 // Allocate our device name
495 Length
= GuidString
.Length
+ 32;
496 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
498 TAG('R', 'a', 'm', 'd'));
504 Status
= STATUS_INSUFFICIENT_RESOURCES
;
509 // Build the device name string
511 DeviceName
.Buffer
= Buffer
;
512 DeviceName
.Length
= Length
- 2;
513 DeviceName
.MaximumLength
= Length
;
514 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
515 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
516 DPRINT1("Creating device: %wZ\n", &DeviceName
);
519 // Create the drive device
521 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
522 sizeof(RAMDISK_DRIVE_EXTENSION
),
524 (Input
->Options
.ExportAsCd
) ?
525 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
529 if (!NT_SUCCESS(Status
)) goto FailCreate
;
532 // Grab the drive extension
534 DriveExtension
= DeviceObject
->DeviceExtension
;
537 // Check if we need a DOS device
539 if (!Input
->Options
.NoDosDevice
)
542 // Build the symbolic link name
544 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
545 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
546 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
547 SymbolicLinkName
.MaximumLength
,
548 TAG('R', 'a', 'm', 'd'));
549 SymbolicLinkName
.Buffer
= Buffer
;
556 L
"\\GLOBAL??\\Ramdisk",
557 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
560 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
561 DPRINT1("Creating symbolic link: %wZ to %wZ \n",
562 &SymbolicLinkName
, &DeviceName
);
563 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
564 if (!NT_SUCCESS(Status
))
569 Input
->Options
.NoDosDevice
= TRUE
;
571 SymbolicLinkName
.Buffer
= NULL
;
579 Input
->Options
.NoDosDevice
= TRUE
;
583 // It this an ISO boot ramdisk?
585 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
588 // Does it need a drive letter?
590 if (!Input
->Options
.NoDriveLetter
)
593 // Build it and take over the existing symbolic link
595 _snwprintf(LocalBuffer
,
597 L
"\\DosDevices\\%wc:",
599 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
600 DPRINT1("Creating symbolic link: %wZ to %wZ\n",
601 &DriveString
, &DeviceName
);
602 IoDeleteSymbolicLink(&DriveString
);
603 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
606 // Save the drive letter
608 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
615 // Setup the device object flags
617 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
618 DeviceObject
->AlignmentRequirement
= 1;
621 // Build the drive FDO
623 *NewDriveExtension
= DriveExtension
;
624 DriveExtension
->Type
= RamdiskDrive
;
625 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
626 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
627 TAG('R', 'a', 'm', 'd'),
630 DriveExtension
->DriveDeviceName
= DeviceName
;
631 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
632 DriveExtension
->GuidString
= GuidString
;
633 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
634 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
635 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
636 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
637 DriveExtension
->DiskType
= Input
->DiskType
;
638 DriveExtension
->DiskOptions
= Input
->Options
;
639 DriveExtension
->DiskLength
= Input
->DiskLength
;
640 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
641 DriveExtension
->BasePage
= Input
->BasePage
;
644 // Make sure we don't free it later
646 DeviceName
.Buffer
= NULL
;
647 SymbolicLinkName
.Buffer
= NULL
;
648 GuidString
.Buffer
= NULL
;
651 // Check if this is an boot disk, or a registry ram drive
653 if (!(Input
->Options
.ExportAsCd
) &&
654 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
657 // Not an ISO boot, but it's a boot FS -- map it to figure out the
660 CurrentOffset
.QuadPart
= 0;
661 BaseAddress
= RamdiskMapPages(DriveExtension
,
670 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
671 BytesPerSector
= BootSector
->PackedBpb
.BytesPerSector
[0];
672 SectorsPerTrack
= BootSector
->PackedBpb
.SectorsPerTrack
[0];
673 Heads
= BootSector
->PackedBpb
.Heads
[0];
678 DriveExtension
->BytesPerSector
= BytesPerSector
;
679 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
680 DriveExtension
->NumberOfHeads
= Heads
;
685 CurrentOffset
.QuadPart
= 0;
686 RamdiskUnmapPages(DriveExtension
,
696 Status
= STATUS_INSUFFICIENT_RESOURCES
;
702 // Sanity check for debugging
704 DPRINT1("[RAMDISK] Loaded...\n"
705 "Bytes per Sector: %d\n"
706 "Sectors per Track: %d\n"
707 "Number of Heads: %d\n",
708 DriveExtension
->BytesPerSector
,
709 DriveExtension
->SectorsPerTrack
,
710 DriveExtension
->NumberOfHeads
);
713 // Check if the drive settings haven't been set yet
715 if ((DriveExtension
->BytesPerSector
== 0) ||
716 (DriveExtension
->SectorsPerTrack
== 0) ||
717 (DriveExtension
->NumberOfHeads
== 0))
720 // Check if this is a CD
722 if (Input
->Options
.ExportAsCd
)
725 // Setup partition parameters default for ISO 9660
727 DriveExtension
->BytesPerSector
= 2048;
728 DriveExtension
->SectorsPerTrack
= 32;
729 DriveExtension
->NumberOfHeads
= 64;
734 // Setup partition parameters default for FAT
736 DriveExtension
->BytesPerSector
= 512;
737 DriveExtension
->SectorsPerTrack
= 128;
738 DriveExtension
->NumberOfHeads
= 16;
743 // Acquire the disk lock
745 KeEnterCriticalRegion();
746 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
751 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
756 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
757 KeLeaveCriticalRegion();
762 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
763 return STATUS_SUCCESS
;
769 return STATUS_SUCCESS
;
774 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
776 IN BOOLEAN ValidateOnly
)
778 PRAMDISK_CREATE_INPUT Input
;
780 PRAMDISK_BUS_EXTENSION DeviceExtension
;
781 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
783 PWCHAR FileNameStart
, FileNameEnd
;
785 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
788 // Get the device extension and our input data
790 DeviceExtension
= DeviceObject
->DeviceExtension
;
791 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
792 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
795 // Validate input parameters
797 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
798 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
803 return STATUS_INVALID_PARAMETER
;
807 // Validate the disk type
809 DiskType
= Input
->DiskType
;
810 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
813 // Look at the disk type
815 if (DiskType
== RAMDISK_BOOT_DISK
)
818 // We only allow this as an early-init boot
820 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
823 // Save command-line flags
825 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
826 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
830 // Validate the disk type
832 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
835 // If the type isn't CDFS, it has to at least be raw CD
837 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
841 // Check if this is an actual file
843 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
846 // Validate the file name
848 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
849 FileNameEnd
= Input
->FileName
+ 1;
850 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
851 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
855 // Create the actual device
857 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
861 if (NT_SUCCESS(Status
))
864 // Invalidate and set success
866 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
867 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
878 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
881 PRAMDISK_BUS_EXTENSION DeviceExtension
;
883 PIO_STACK_LOCATION IoStackLocation
;
887 // Get the stack location
889 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
892 // Free the work item
894 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
897 // Grab the device extension and lock it
899 DeviceExtension
= DeviceObject
->DeviceExtension
;
900 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
901 if (NT_SUCCESS(Status
))
904 // Discriminate by major code
906 switch (IoStackLocation
->MajorFunction
)
911 case IRP_MJ_DEVICE_CONTROL
:
914 // Let's take a look at the IOCTL
916 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
919 // Ramdisk create request
921 case FSCTL_CREATE_RAM_DISK
:
924 // This time we'll do it for real
926 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
929 case IOCTL_DISK_SET_PARTITION_INFO
:
931 DPRINT1("Set partition info request\n");
936 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
938 DPRINT1("Get drive layout request\n");
943 case IOCTL_DISK_GET_PARTITION_INFO
:
945 DPRINT1("Get partitinon info request\n");
952 DPRINT1("Invalid request\n");
964 // Read or write request
969 DPRINT1("Read/Write request\n");
975 // Internal request (SCSI?)
977 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
979 DPRINT1("SCSI request\n");
987 case IRP_MJ_FLUSH_BUFFERS
:
989 DPRINT1("Flush request\n");
999 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1008 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1009 Irp
->IoStatus
.Status
= Status
;
1010 Irp
->IoStatus
.Information
= 0;
1011 return IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1017 Irp
->IoStatus
.Status
= Status
;
1018 Irp
->IoStatus
.Information
= 0;
1019 return IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1024 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1027 PIO_WORKITEM WorkItem
;
1030 // Mark the IRP pending
1032 IoMarkIrpPending(Irp
);
1035 // Allocate a work item
1037 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1043 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1044 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1045 return STATUS_PENDING
;
1052 return STATUS_INSUFFICIENT_RESOURCES
;
1058 RamdiskReadWriteReal(IN PIRP Irp
,
1059 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1062 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1063 PIO_STACK_LOCATION IoStackLocation
;
1064 LARGE_INTEGER CurrentOffset
;
1065 ULONG BytesRead
, BytesLeft
, CopyLength
;
1066 PVOID Source
, Destination
;
1070 // Get the MDL and check if it's mapped
1072 Mdl
= Irp
->MdlAddress
;
1073 if (Mdl
->MdlFlags
& MDL_MAPPED_TO_SYSTEM_VA
)
1076 // Use the mapped address
1078 SystemVa
= Mdl
->MappedSystemVa
;
1085 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1090 NormalPagePriority
);
1094 // Make sure we were able to map it
1096 CurrentBase
= SystemVa
;
1097 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1100 // Initialize default
1102 Irp
->IoStatus
.Information
= 0;
1105 // Get the I/O Stack Location and capture the data
1107 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1108 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1109 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1110 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1115 DPRINT1("Initiating copy loop for %lx bytes at %p\n", BytesLeft
, SystemVa
);
1121 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1125 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1128 // Update our lengths
1130 Irp
->IoStatus
.Information
+= BytesRead
;
1131 CopyLength
= BytesRead
;
1134 // Check if this was a read or write
1136 Status
= STATUS_SUCCESS
;
1137 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1140 // Set our copy parameters
1142 Destination
= CurrentBase
;
1143 Source
= BaseAddress
;
1146 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1149 // Set our copy parameters
1151 Destination
= BaseAddress
;
1152 Source
= CurrentBase
;
1157 RtlCopyMemory(Destination
, Source
, CopyLength
);
1162 // Prepare us for failure
1164 BytesLeft
= CopyLength
;
1165 Status
= STATUS_INVALID_PARAMETER
;
1171 RamdiskUnmapPages(DeviceExtension
,
1177 // Update offset and bytes left
1179 BytesLeft
-= BytesRead
;
1180 CurrentOffset
.QuadPart
+= BytesRead
;
1181 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1184 // Check if we're done
1186 if (!BytesLeft
) return Status
;
1192 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1198 Irp
->IoStatus
.Information
= 1;
1199 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1200 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1201 return STATUS_SUCCESS
;
1206 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1209 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1211 LARGE_INTEGER ByteOffset
;
1212 PIO_STACK_LOCATION IoStackLocation
;
1213 NTSTATUS Status
, ReturnStatus
;
1216 // Get the device extension and make sure this isn't a bus
1218 DeviceExtension
= DeviceObject
->DeviceExtension
;
1219 if (DeviceExtension
->Type
== RamdiskBus
)
1224 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1229 // Capture parameters
1231 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1232 Length
= IoStackLocation
->Parameters
.Read
.Length
;
1233 ByteOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1236 // FIXME: Validate offset
1240 // FIXME: Validate sector
1246 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1247 (DeviceExtension
->DiskOptions
.Readonly
))
1250 // Fail, this is read-only
1252 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1257 // See if we want to do this sync or async
1259 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1264 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1269 // Queue it to the worker
1271 Status
= SendIrpToThread(DeviceObject
, Irp
);
1272 ReturnStatus
= STATUS_PENDING
;
1275 // Check if we're pending or not
1277 if (Status
!= STATUS_PENDING
)
1283 Irp
->IoStatus
.Status
= Status
;
1284 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1285 ReturnStatus
= Status
;
1291 return ReturnStatus
;
1296 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1300 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1301 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1306 // Grab 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 // Setup some defaults
1323 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1327 // Check if this is an bus device or the drive
1329 if (DeviceExtension
->Type
== RamdiskBus
)
1332 // Check what the request is
1334 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1337 // Request to create a ramdisk
1339 case FSCTL_CREATE_RAM_DISK
:
1344 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1345 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1351 // We don't handle anything else yet
1360 // Check what the request is
1362 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1364 case IOCTL_DISK_CHECK_VERIFY
:
1365 case IOCTL_STORAGE_CHECK_VERIFY
:
1366 case IOCTL_STORAGE_CHECK_VERIFY2
:
1367 case IOCTL_CDROM_CHECK_VERIFY
:
1373 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1374 case IOCTL_DISK_GET_MEDIA_TYPES
:
1375 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1376 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1383 // Hack to support ReactOS's broken CDFS
1385 case IOCTL_CDROM_GET_LAST_SESSION
:
1388 // Validate the length
1390 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1391 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1396 Status
= STATUS_BUFFER_TOO_SMALL
;
1403 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1405 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1406 Toc
->FirstTrack
= 1;
1408 Toc
->TrackData
[0].Adr
= 1;
1409 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1410 Toc
->TrackData
[0].TrackNumber
= 1;
1411 Toc
->TrackData
[0].Address
[0] =
1412 Toc
->TrackData
[0].Address
[1] =
1413 Toc
->TrackData
[0].Address
[2] =
1414 Toc
->TrackData
[0].Address
[3] = 0;
1419 Status
= STATUS_SUCCESS
;
1420 Information
= RAMDISK_SESSION_SIZE
;
1423 case IOCTL_CDROM_READ_TOC
:
1426 // Validate the length
1428 DPRINT1("Output: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.OutputBufferLength
);
1429 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1430 OutputBufferLength
< sizeof(CDROM_TOC
))
1435 Status
= STATUS_BUFFER_TOO_SMALL
;
1442 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1443 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1448 DPRINT1("TOC: %d\n", RAMDISK_TOC_SIZE
);
1450 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1451 Toc
->FirstTrack
= 1;
1453 Toc
->TrackData
[0].Adr
= 1;
1454 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1455 Toc
->TrackData
[0].TrackNumber
= 1;
1460 Status
= STATUS_SUCCESS
;
1461 Information
= RAMDISK_TOC_SIZE
;
1464 case IOCTL_DISK_SET_PARTITION_INFO
:
1470 case IOCTL_DISK_GET_PARTITION_INFO
:
1476 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1482 case IOCTL_DISK_GET_LENGTH_INFO
:
1488 case IOCTL_DISK_IS_WRITABLE
:
1494 case IOCTL_SCSI_MINIPORT
:
1500 case IOCTL_STORAGE_QUERY_PROPERTY
:
1506 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1512 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1518 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1524 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1530 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1536 case IOCTL_VOLUME_OFFLINE
:
1545 // Drive code not emulated
1547 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1552 // If requests drop down here, we just return them complete them
1554 goto CompleteRequest
;
1558 // Queue the request to our worker thread
1560 Status
= SendIrpToThread(DeviceObject
, Irp
);
1566 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1567 if (Status
!= STATUS_PENDING
)
1570 // Complete the request
1572 Irp
->IoStatus
.Status
= Status
;
1573 Irp
->IoStatus
.Information
= Information
;
1574 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1585 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1586 IN PDEVICE_OBJECT DeviceObject
,
1589 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1590 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1591 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1592 ULONG Count
, DiskCount
, FinalCount
;
1593 PLIST_ENTRY ListHead
, NextEntry
;
1594 PDEVICE_OBJECT
* DriveDeviceObject
;
1595 RAMDISK_DEVICE_STATE State
;
1598 // Get the device extension and check if this is a drive
1600 DeviceExtension
= DeviceObject
->DeviceExtension
;
1601 if (DeviceExtension
->Type
== RamdiskDrive
)
1611 // Anything but bus relations, we don't handle
1613 if (Type
) goto PassToNext
;
1616 // Acquire the disk list lock
1618 KeEnterCriticalRegion();
1619 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1622 // Did a device already fill relations?
1624 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1625 if (DeviceRelations
)
1630 Count
= DeviceRelations
->Count
;
1641 // Now loop our drives
1644 ListHead
= &DeviceExtension
->DiskList
;
1645 NextEntry
= ListHead
->Flink
;
1646 while (NextEntry
!= ListHead
)
1649 // As long as it wasn't removed, count it in
1651 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1652 RAMDISK_DRIVE_EXTENSION
,
1654 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1657 // Move to the next one
1659 NextEntry
= NextEntry
->Flink
;
1663 // Now we know our final count
1665 FinalCount
= Count
+ DiskCount
;
1668 // Allocate the structure
1670 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1671 FIELD_OFFSET(DEVICE_RELATIONS
,
1674 sizeof(PDEVICE_OBJECT
),
1675 TAG('R', 'a', 'm', 'd'));
1676 if (!OurDeviceRelations
)
1681 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1682 KeLeaveCriticalRegion();
1683 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1684 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1685 return STATUS_INSUFFICIENT_RESOURCES
;
1689 // Check if we already had some relations
1696 RtlCopyMemory(OurDeviceRelations
->Objects
,
1697 DeviceRelations
->Objects
,
1698 Count
* sizeof(PDEVICE_OBJECT
));
1704 OurDeviceRelations
->Count
= FinalCount
;
1707 // Now loop our drives again
1709 ListHead
= &DeviceExtension
->DiskList
;
1710 NextEntry
= ListHead
->Flink
;
1711 while (NextEntry
!= ListHead
)
1714 // Go to the end of the list
1716 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1719 // Get the drive state
1721 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1722 RAMDISK_DRIVE_EXTENSION
,
1724 State
= DriveExtension
->State
;
1727 // If it was removed or enumerated, we don't touch the device object
1729 if (State
>= RamdiskStateBusRemoved
)
1732 // If it was removed, we still have to keep track of this though
1734 if (State
== RamdiskStateBusRemoved
)
1737 // Mark it as enumerated now, but don't actually reference it
1739 DriveExtension
->State
= RamdiskStateEnumerated
;
1745 // First time it's enumerated, reference the device object
1747 ObReferenceObject(DriveExtension
->DeviceObject
);
1750 // Save the object pointer, and move on
1752 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1755 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1758 // Move to the next one
1760 NextEntry
= NextEntry
->Flink
;
1766 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1767 KeLeaveCriticalRegion();
1770 // Cleanup old relations
1772 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1777 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1778 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1781 // Pass to the next driver
1784 IoCopyCurrentIrpStackLocationToNext(Irp
);
1785 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1790 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1793 PIO_STACK_LOCATION IoStackLocation
;
1794 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1799 // Get the device extension and stack location
1801 DeviceExtension
= DeviceObject
->DeviceExtension
;
1802 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1803 Minor
= IoStackLocation
->MinorFunction
;
1806 // Check if the bus is removed
1808 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1811 // Only remove-device and query-id are allowed
1813 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
1816 // Fail anything else
1818 Status
= STATUS_NO_SUCH_DEVICE
;
1819 Irp
->IoStatus
.Status
= Status
;
1820 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1826 // Acquire the remove lock
1828 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1829 if (!NT_SUCCESS(Status
))
1834 Irp
->IoStatus
.Information
= 0;
1835 Irp
->IoStatus
.Status
= Status
;
1836 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1841 // Query the IRP type
1845 case IRP_MN_START_DEVICE
:
1847 DPRINT1("PnP IRP: %lx\n", Minor
);
1851 case IRP_MN_QUERY_STOP_DEVICE
:
1853 DPRINT1("PnP IRP: %lx\n", Minor
);
1857 case IRP_MN_CANCEL_STOP_DEVICE
:
1859 DPRINT1("PnP IRP: %lx\n", Minor
);
1863 case IRP_MN_STOP_DEVICE
:
1865 DPRINT1("PnP IRP: %lx\n", Minor
);
1869 case IRP_MN_QUERY_REMOVE_DEVICE
:
1871 DPRINT1("PnP IRP: %lx\n", Minor
);
1875 case IRP_MN_CANCEL_REMOVE_DEVICE
:
1877 DPRINT1("PnP IRP: %lx\n", Minor
);
1881 case IRP_MN_REMOVE_DEVICE
:
1883 DPRINT1("PnP IRP: %lx\n", Minor
);
1887 case IRP_MN_SURPRISE_REMOVAL
:
1889 DPRINT1("PnP IRP: %lx\n", Minor
);
1893 case IRP_MN_QUERY_ID
:
1898 if (DeviceExtension
->Type
== RamdiskDrive
)
1900 DPRINT1("PnP IRP: %lx\n", Minor
);
1905 case IRP_MN_QUERY_BUS_INFORMATION
:
1910 if (DeviceExtension
->Type
== RamdiskDrive
)
1912 DPRINT1("PnP IRP: %lx\n", Minor
);
1919 DPRINT1("PnP IRP: %lx\n", Minor
);
1923 case IRP_MN_QUERY_DEVICE_TEXT
:
1928 if (DeviceExtension
->Type
== RamdiskDrive
)
1930 DPRINT1("PnP IRP: %lx\n", Minor
);
1935 case IRP_MN_QUERY_DEVICE_RELATIONS
:
1938 // Call our main routine
1940 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
1942 QueryDeviceRelations
.Type
,
1945 goto ReleaseAndReturn
;
1947 case IRP_MN_QUERY_CAPABILITIES
:
1952 if (DeviceExtension
->Type
== RamdiskDrive
)
1954 DPRINT1("PnP IRP: %lx\n", Minor
);
1959 case IRP_MN_QUERY_RESOURCES
:
1960 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
1963 // Complete immediately without touching it
1965 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1966 goto ReleaseAndReturn
;
1970 DPRINT1("Illegal IRP: %lx\n", Minor
);
1977 if (DeviceExtension
->Type
== RamdiskBus
)
1980 // Do we have an attached device?
1982 if (DeviceExtension
->AttachedDevice
)
1987 IoSkipCurrentIrpStackLocation(Irp
);
1988 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1993 // Release the lock and return status
1996 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2002 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2007 return STATUS_SUCCESS
;
2012 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2017 return STATUS_SUCCESS
;
2022 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2027 return STATUS_SUCCESS
;
2032 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2037 return STATUS_SUCCESS
;
2042 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2050 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2051 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2053 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2054 PDEVICE_OBJECT AttachedDevice
;
2056 UNICODE_STRING DeviceName
;
2057 PDEVICE_OBJECT DeviceObject
;
2060 // Only create the bus FDO once
2062 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2065 // Create the bus FDO
2067 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2068 Status
= IoCreateDevice(DriverObject
,
2069 sizeof(RAMDISK_BUS_EXTENSION
),
2071 FILE_DEVICE_BUS_EXTENDER
,
2072 FILE_DEVICE_SECURE_OPEN
,
2075 if (NT_SUCCESS(Status
))
2078 // Initialize the bus FDO extension
2080 DeviceExtension
= DeviceObject
->DeviceExtension
;
2081 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2082 sizeof(RAMDISK_BUS_EXTENSION
));
2085 // Set bus FDO flags
2087 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2090 // Setup the bus FDO extension
2092 DeviceExtension
->Type
= RamdiskBus
;
2093 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2094 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2095 TAG('R', 'a', 'm', 'd'),
2098 InitializeListHead(&DeviceExtension
->DiskList
);
2099 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2100 DeviceExtension
->DeviceObject
= DeviceObject
;
2103 // Register the RAM disk device interface
2105 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2106 &RamdiskBusInterface
,
2108 &DeviceExtension
->BusDeviceName
);
2109 if (!NT_SUCCESS(Status
))
2114 IoDeleteDevice(DeviceObject
);
2119 // Attach us to the device stack
2121 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2122 PhysicalDeviceObject
);
2123 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2124 if (!AttachedDevice
)
2129 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2130 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2131 IoDeleteDevice(DeviceObject
);
2132 return STATUS_NO_SUCH_DEVICE
;
2136 // Bus FDO is initialized
2138 RamdiskBusFdo
= DeviceObject
;
2141 // Loop for loader block
2146 // Are we being booted from setup? Not yet supported
2148 ASSERT (!KeLoaderBlock
->SetupLdrBlock
);
2154 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2155 Status
= STATUS_SUCCESS
;
2166 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2167 IN PUNICODE_STRING RegistryPath
)
2169 PCHAR BootDeviceName
, CommandLine
;
2170 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2174 // Query ramdisk parameters
2176 QueryParameters(RegistryPath
);
2179 // Save the registry path
2181 DriverRegistryPath
= *RegistryPath
;
2182 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2183 RegistryPath
->Length
+
2185 TAG('R', 'a', 'm', 'd'));
2186 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2187 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2190 // Set device routines
2192 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2193 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2194 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2195 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2196 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2197 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2198 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2199 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2200 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2201 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2202 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2203 DriverObject
->DriverUnload
= RamdiskUnload
;
2206 // Check for a loader block
2211 // Get the boot device name
2213 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2217 // Check if we're booting from ramdisk
2219 if ((strlen(BootDeviceName
) >= 10) &&
2220 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2223 // We'll have to tell the PnP Manager
2225 ReportDetectedDevice
= TRUE
;
2228 // Check for a command line
2230 CommandLine
= KeLoaderBlock
->LoadOptions
;
2234 // Check if this is an ISO boot
2236 if (strstr(CommandLine
, "RDEXPORTASCD"))
2239 // Remember for later
2241 ExportBootDiskAsCd
= TRUE
;
2245 // Check if this is PE boot
2247 if (strstr(CommandLine
, "MININT"))
2250 // Remember for later
2261 // Installing from Ramdisk isn't supported yet
2263 ASSERT(!KeLoaderBlock
->SetupLdrBlock
);
2266 // Are we reporting the device
2268 if (ReportDetectedDevice
)
2273 Status
= IoReportDetectedDevice(DriverObject
,
2274 InterfaceTypeUndefined
,
2280 &PhysicalDeviceObject
);
2281 if (NT_SUCCESS(Status
))
2285 // The ReactOS Plug and Play Manager is broken and does not create
2286 // the required keys when reporting a detected device.
2287 // We hack around this ourselves.
2289 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
2290 PhysicalDeviceObject
->DeviceObjectExtension
)
2291 ->DeviceNode
->InstancePath
,
2292 L
"Root\\UNKNOWN\\0000");
2295 // Create the device object
2297 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2298 if (NT_SUCCESS(Status
))
2303 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2304 Status
= STATUS_SUCCESS
;
2313 Status
= STATUS_SUCCESS
;