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 #define DO_XIP 0x00020000
33 /* GLOBALS ********************************************************************/
35 #define RAMDISK_SESSION_SIZE \
36 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
38 #define RAMDISK_TOC_SIZE \
39 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
41 #define TOC_DATA_TRACK (0x04)
43 typedef enum _RAMDISK_DEVICE_TYPE
47 } RAMDISK_DEVICE_TYPE
;
49 typedef enum _RAMDISK_DEVICE_STATE
51 RamdiskStateUninitialized
,
56 RamdiskStateBusRemoved
,
57 RamdiskStateEnumerated
,
58 } RAMDISK_DEVICE_STATE
;
60 DEFINE_GUID(RamdiskBusInterface
,
64 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
66 typedef struct _RAMDISK_EXTENSION
68 RAMDISK_DEVICE_TYPE Type
;
69 RAMDISK_DEVICE_STATE State
;
70 PDEVICE_OBJECT DeviceObject
;
71 PDEVICE_OBJECT PhysicalDeviceObject
;
72 PDEVICE_OBJECT AttachedDevice
;
73 IO_REMOVE_LOCK RemoveLock
;
74 UNICODE_STRING DriveDeviceName
;
75 UNICODE_STRING BusDeviceName
;
76 FAST_MUTEX DiskListLock
;
78 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
80 typedef struct _RAMDISK_BUS_EXTENSION
83 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
85 typedef struct _RAMDISK_DRIVE_EXTENSION
88 // Inherited base class
93 // Data we get from the creator
96 UNICODE_STRING GuidString
;
97 UNICODE_STRING SymbolicLinkName
;
99 RAMDISK_CREATE_OPTIONS DiskOptions
;
100 LARGE_INTEGER DiskLength
;
106 // Data we get from the disk
108 ULONG BytesPerSector
;
109 ULONG SectorsPerTrack
;
113 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
115 ULONG MaximumViewLength
;
116 ULONG MaximumPerDiskViewLength
;
117 ULONG ReportDetectedDevice
;
118 ULONG MarkRamdisksAsRemovable
;
119 ULONG MinimumViewCount
;
120 ULONG DefaultViewCount
;
121 ULONG MaximumViewCount
;
122 ULONG MinimumViewLength
;
123 ULONG DefaultViewLength
;
124 UNICODE_STRING DriverRegistryPath
;
125 BOOLEAN ExportBootDiskAsCd
;
127 PDEVICE_OBJECT RamdiskBusFdo
;
129 /* FUNCTIONS ******************************************************************/
133 QueryParameters(IN PUNICODE_STRING RegistryPath
)
135 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
136 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
141 MaximumViewLength
= 0x10000000u
;
142 MaximumPerDiskViewLength
= 0x10000000u
;
143 ReportDetectedDevice
= 0;
144 MarkRamdisksAsRemovable
= 0;
145 MinimumViewCount
= 2;
146 DefaultViewCount
= 16;
147 MaximumViewCount
= 64;
148 MinimumViewLength
= 0x10000u
;
149 DefaultViewLength
= 0x100000u
;
152 // Setup the query table and query the registry
154 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
155 QueryTable
[0].Flags
= 1;
156 QueryTable
[0].Name
= L
"Parameters";
157 QueryTable
[1].Flags
= 32;
158 QueryTable
[1].Name
= L
"ReportDetectedDevice";
159 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
160 QueryTable
[2].Flags
= 32;
161 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
162 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
163 QueryTable
[3].Flags
= 32;
164 QueryTable
[3].Name
= L
"MinimumViewCount";
165 QueryTable
[3].EntryContext
= &MinimumViewCount
;
166 QueryTable
[4].Flags
= 32;
167 QueryTable
[4].Name
= L
"DefaultViewCount";
168 QueryTable
[4].EntryContext
= &DefaultViewCount
;
169 QueryTable
[5].Flags
= 32;
170 QueryTable
[5].Name
= L
"MaximumViewCount";
171 QueryTable
[5].EntryContext
= &MaximumViewCount
;
172 QueryTable
[6].Flags
= 32;
173 QueryTable
[6].Name
= L
"MinimumViewLength";
174 QueryTable
[6].EntryContext
= &MinimumViewLength
;
175 QueryTable
[7].Flags
= 32;
176 QueryTable
[7].Name
= L
"DefaultViewLength";
177 QueryTable
[7].EntryContext
= &DefaultViewLength
;
178 QueryTable
[8].Flags
= 32;
179 QueryTable
[8].Name
= L
"MaximumViewLength";
180 QueryTable
[8].EntryContext
= &MaximumViewLength
;
181 QueryTable
[9].Flags
= 32;
182 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
183 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
184 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
185 RegistryPath
->Buffer
,
191 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
193 MinView
= MinimumViewCount
;
194 if (MinimumViewCount
>= 2)
196 if (MinimumViewCount
> 256) MinView
= 256;
202 MinimumViewCount
= MinView
;
205 // Parse default view count, cannot be bigger than 256 or smaller than minimum
207 DefView
= DefaultViewCount
;
208 if (DefaultViewCount
>= MinView
)
210 if (DefaultViewCount
> 256) DefView
= 256;
216 DefaultViewCount
= DefView
;
219 // Parse maximum view count, cannot be bigger than 256 or smaller than default
221 if (MaximumViewCount
>= DefView
)
223 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
227 MaximumViewCount
= DefView
;
231 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
233 MinViewLength
= MinimumViewLength
;
234 if (MinimumViewLength
>= 0x10000)
236 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
240 MinViewLength
= 0x10000u
;
242 MinimumViewLength
= MinViewLength
;
245 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
247 DefViewLength
= DefaultViewLength
;
248 if (DefaultViewLength
>= MinViewLength
)
250 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
254 DefViewLength
= MinViewLength
;
256 DefaultViewLength
= DefViewLength
;
259 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
261 MaxViewLength
= MaximumViewLength
;
262 if (MaximumViewLength
>= DefViewLength
)
264 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
268 MaxViewLength
= DefViewLength
;
270 MaximumViewLength
= MaxViewLength
;
273 // Parse maximum view length per disk, cannot be smaller than 16MB
275 if (MaximumPerDiskViewLength
>= 0x1000000)
277 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
281 MaximumPerDiskViewLength
= 0x1000000u
;
287 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
288 IN LARGE_INTEGER Offset
,
290 OUT PULONG OutputLength
)
292 PHYSICAL_ADDRESS PhysicalAddress
;
296 LARGE_INTEGER ActualOffset
;
297 LARGE_INTEGER ActualPages
;
300 // We only support boot disks for now
302 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
305 // Calculate the actual offset in the drive
307 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
312 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
315 // Now add the base page
317 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
320 // Calculate final amount of bytes
322 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
325 // Calculate pages spanned for the mapping
327 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
330 // And convert this back to bytes
332 ActualLength
<<= PAGE_SHIFT
;
335 // Get the offset within the page
337 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
340 // Map the I/O Space from the loader
342 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
345 // Return actual offset within the page as well as the length
347 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
348 *OutputLength
= Length
;
354 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
355 IN PVOID BaseAddress
,
356 IN LARGE_INTEGER Offset
,
359 LARGE_INTEGER ActualOffset
;
364 // We only support boot disks for now
366 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
369 // Calculate the actual offset in the drive
371 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
374 // Calculate pages spanned for the mapping
376 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
379 // And convert this back to bytes
381 ActualLength
<<= PAGE_SHIFT
;
384 // Get the offset within the page
386 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
389 // Calculate actual base address where we mapped this
391 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
394 // Unmap the I/O space we got from the loader
396 MmUnmapIoSpace(BaseAddress
, ActualLength
);
401 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
402 IN PRAMDISK_CREATE_INPUT Input
,
403 IN BOOLEAN ValidateOnly
,
404 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
406 ULONG BasePage
, 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 BIOS_PARAMETER_BLOCK BiosBlock
;
416 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
418 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
419 ULONG CylinderCount
, SizeByCylinders
;
422 // Check if we're a boot RAM disk
424 DiskType
= Input
->DiskType
;
425 if (DiskType
>= RAMDISK_BOOT_DISK
)
428 // Check if we're an ISO
430 if (DiskType
== RAMDISK_BOOT_DISK
)
433 // NTLDR mounted us somewhere
435 BasePage
= Input
->BasePage
;
436 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
439 // Sanitize disk options
441 Input
->Options
.Fixed
= TRUE
;
442 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
443 Input
->Options
.Readonly
;
444 Input
->Options
.Hidden
= FALSE
;
445 Input
->Options
.NoDosDevice
= FALSE
;
446 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
451 // The only other possibility is a WIM disk
453 if (DiskType
!= RAMDISK_WIM_DISK
)
458 return STATUS_INVALID_PARAMETER
;
462 // Read the view count instead
464 //ViewCount = Input->ViewCount;
467 // Sanitize disk options
469 Input
->Options
.Hidden
= FALSE
;
470 Input
->Options
.NoDosDevice
= FALSE
;
471 Input
->Options
.Readonly
= FALSE
;
472 Input
->Options
.NoDriveLetter
= TRUE
;
473 Input
->Options
.Fixed
= TRUE
;
477 // Are we just validating and returning to the user?
479 if (ValidateOnly
) return STATUS_SUCCESS
;
482 // Build the GUID string
484 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
485 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
490 Status
= STATUS_INSUFFICIENT_RESOURCES
;
495 // Allocate our device name
497 Length
= GuidString
.Length
+ 32;
498 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
506 Status
= STATUS_INSUFFICIENT_RESOURCES
;
511 // Build the device name string
513 DeviceName
.Buffer
= Buffer
;
514 DeviceName
.Length
= Length
- 2;
515 DeviceName
.MaximumLength
= Length
;
516 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
517 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
520 // Create the drive device
522 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
523 sizeof(RAMDISK_DRIVE_EXTENSION
),
525 (Input
->Options
.ExportAsCd
) ?
526 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
530 if (!NT_SUCCESS(Status
)) goto FailCreate
;
533 // Grab the drive extension
535 DriveExtension
= DeviceObject
->DeviceExtension
;
538 // Check if we need a DOS device
540 if (!Input
->Options
.NoDosDevice
)
543 // Build the symbolic link name
545 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
546 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
547 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
548 SymbolicLinkName
.MaximumLength
,
550 SymbolicLinkName
.Buffer
= Buffer
;
557 L
"\\GLOBAL??\\Ramdisk",
558 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
561 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
562 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
563 if (!NT_SUCCESS(Status
))
568 Input
->Options
.NoDosDevice
= TRUE
;
570 SymbolicLinkName
.Buffer
= NULL
;
578 Input
->Options
.NoDosDevice
= TRUE
;
582 // It this an ISO boot ramdisk?
584 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
587 // Does it need a drive letter?
589 if (!Input
->Options
.NoDriveLetter
)
592 // Build it and take over the existing symbolic link
594 _snwprintf(LocalBuffer
,
596 L
"\\DosDevices\\%wc:",
598 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
599 IoDeleteSymbolicLink(&DriveString
);
600 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
603 // Save the drive letter
605 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
612 // Setup the device object flags
614 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
615 DeviceObject
->AlignmentRequirement
= 1;
618 // Build the drive FDO
620 *NewDriveExtension
= DriveExtension
;
621 DriveExtension
->Type
= RamdiskDrive
;
622 DiskLength
= Input
->DiskLength
;
623 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
624 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
628 DriveExtension
->DriveDeviceName
= DeviceName
;
629 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
630 DriveExtension
->GuidString
= GuidString
;
631 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
632 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
633 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
634 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
635 DriveExtension
->DiskType
= Input
->DiskType
;
636 DriveExtension
->DiskOptions
= Input
->Options
;
637 DriveExtension
->DiskLength
= DiskLength
;
638 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
639 DriveExtension
->BasePage
= Input
->BasePage
;
640 DriveExtension
->BytesPerSector
= 0;
641 DriveExtension
->SectorsPerTrack
= 0;
642 DriveExtension
->NumberOfHeads
= 0;
645 // Make sure we don't free it later
647 DeviceName
.Buffer
= NULL
;
648 SymbolicLinkName
.Buffer
= NULL
;
649 GuidString
.Buffer
= NULL
;
652 // Check if this is an boot disk, or a registry ram drive
654 if (!(Input
->Options
.ExportAsCd
) &&
655 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
658 // Not an ISO boot, but it's a boot FS -- map it to figure out the
661 CurrentOffset
.QuadPart
= 0;
662 BaseAddress
= RamdiskMapPages(DriveExtension
,
671 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
672 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
673 BytesPerSector
= BiosBlock
.BytesPerSector
;
674 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
675 Heads
= BiosBlock
.Heads
;
680 DriveExtension
->BytesPerSector
= BytesPerSector
;
681 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
682 DriveExtension
->NumberOfHeads
= Heads
;
687 CurrentOffset
.QuadPart
= 0;
688 RamdiskUnmapPages(DriveExtension
,
698 Status
= STATUS_INSUFFICIENT_RESOURCES
;
704 // Check if the drive settings haven't been set yet
706 if ((DriveExtension
->BytesPerSector
== 0) ||
707 (DriveExtension
->SectorsPerTrack
== 0) ||
708 (DriveExtension
->NumberOfHeads
== 0))
711 // Check if this is a CD
713 if (Input
->Options
.ExportAsCd
)
716 // Setup partition parameters default for ISO 9660
718 DriveExtension
->BytesPerSector
= 2048;
719 DriveExtension
->SectorsPerTrack
= 32;
720 DriveExtension
->NumberOfHeads
= 64;
725 // Setup partition parameters default for FAT
727 DriveExtension
->BytesPerSector
= 512;
728 DriveExtension
->SectorsPerTrack
= 128;
729 DriveExtension
->NumberOfHeads
= 16;
734 // Calculate the cylinder size
736 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
737 DriveExtension
->SectorsPerTrack
*
738 DriveExtension
->NumberOfHeads
;
739 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
740 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
741 DriveExtension
->Cylinders
= CylinderCount
;
742 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
745 // Align cylinder size up
747 DriveExtension
->Cylinders
++;
751 // Acquire the disk lock
753 KeEnterCriticalRegion();
754 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
759 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
764 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
765 KeLeaveCriticalRegion();
770 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
771 return STATUS_SUCCESS
;
776 ASSERT(FALSE
); // while (TRUE);
777 return STATUS_SUCCESS
;
782 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
784 IN BOOLEAN ValidateOnly
)
786 PRAMDISK_CREATE_INPUT Input
;
788 PRAMDISK_BUS_EXTENSION DeviceExtension
;
789 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
791 PWCHAR FileNameStart
, FileNameEnd
;
793 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
796 // Get the device extension and our input data
798 DeviceExtension
= DeviceObject
->DeviceExtension
;
799 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
800 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
803 // Validate input parameters
805 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
806 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
811 return STATUS_INVALID_PARAMETER
;
815 // Validate the disk type
817 DiskType
= Input
->DiskType
;
818 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
821 // Look at the disk type
823 if (DiskType
== RAMDISK_BOOT_DISK
)
826 // We only allow this as an early-init boot
828 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
831 // Save command-line flags
833 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
834 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
838 // Validate the disk type
840 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
843 // If the type isn't CDFS, it has to at least be raw CD
845 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
849 // Check if this is an actual file
851 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
854 // Validate the file name
856 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
857 FileNameEnd
= Input
->FileName
+ 1;
858 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
859 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
863 // Create the actual device
865 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
869 if (NT_SUCCESS(Status
))
872 // Invalidate and set success
874 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
875 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
886 RamdiskGetPartitionInfo(IN PIRP Irp
,
887 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
890 PPARTITION_INFORMATION PartitionInfo
;
892 LARGE_INTEGER Zero
= {{0, 0}};
894 PIO_STACK_LOCATION IoStackLocation
;
897 // Validate the length
899 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
900 if (IoStackLocation
->Parameters
.DeviceIoControl
.
901 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
906 Status
= STATUS_BUFFER_TOO_SMALL
;
907 Irp
->IoStatus
.Status
= Status
;
908 Irp
->IoStatus
.Information
= 0;
913 // Map the partition table
915 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
921 Status
= STATUS_INSUFFICIENT_RESOURCES
;
922 Irp
->IoStatus
.Status
= Status
;
923 Irp
->IoStatus
.Information
= 0;
928 // Fill out the information
930 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
931 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
932 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
933 DeviceExtension
->SectorsPerTrack
*
934 DeviceExtension
->NumberOfHeads
*
935 DeviceExtension
->Cylinders
;
936 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
937 PartitionInfo
->PartitionNumber
= 0;
938 PartitionInfo
->PartitionType
= *((PCHAR
)BaseAddress
+ 450);
939 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
940 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
941 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
943 PartitionInfo
->RewritePartition
= FALSE
;
946 // Unmap the partition table
948 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
953 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
954 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
955 return STATUS_SUCCESS
;
960 RamdiskSetPartitionInfo(IN PIRP Irp
,
961 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
966 PIO_STACK_LOCATION Stack
;
967 LARGE_INTEGER Zero
= {{0, 0}};
968 PPARTITION_INFORMATION PartitionInfo
;
971 // First validate input
973 Stack
= IoGetCurrentIrpStackLocation(Irp
);
974 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(PARTITION_INFORMATION
))
976 Status
= STATUS_INVALID_PARAMETER
;
983 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &BytesRead
);
984 if (BaseAddress
== NULL
)
986 Status
= STATUS_INSUFFICIENT_RESOURCES
;
991 // Set the new partition type
992 // On partition 0, field system indicator
994 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
995 *((PCHAR
)BaseAddress
+ 450) = PartitionInfo
->PartitionType
;
1000 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, BytesRead
);
1001 Status
= STATUS_SUCCESS
;
1004 Irp
->IoStatus
.Status
= Status
;
1005 Irp
->IoStatus
.Information
= 0;
1011 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
1014 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1016 PIO_STACK_LOCATION IoStackLocation
;
1020 // Get the stack location
1022 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1025 // Free the work item
1027 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
1030 // Grab the device extension and lock it
1032 DeviceExtension
= DeviceObject
->DeviceExtension
;
1033 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1034 if (NT_SUCCESS(Status
))
1037 // Discriminate by major code
1039 switch (IoStackLocation
->MajorFunction
)
1044 case IRP_MJ_DEVICE_CONTROL
:
1047 // Let's take a look at the IOCTL
1049 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1052 // Ramdisk create request
1054 case FSCTL_CREATE_RAM_DISK
:
1057 // This time we'll do it for real
1059 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
1062 case IOCTL_DISK_SET_PARTITION_INFO
:
1064 Status
= RamdiskSetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
1067 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1069 DPRINT1("Get drive layout request\n");
1071 ASSERT(FALSE
); // while (TRUE);
1074 case IOCTL_DISK_GET_PARTITION_INFO
:
1076 Status
= RamdiskGetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
1081 DPRINT1("Invalid request\n");
1083 ASSERT(FALSE
); // while (TRUE);
1093 // Read or write request
1098 DPRINT1("Read/Write request\n");
1100 ASSERT(FALSE
); // while (TRUE);
1104 // Internal request (SCSI?)
1106 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1108 DPRINT1("SCSI request\n");
1110 ASSERT(FALSE
); // while (TRUE);
1116 case IRP_MJ_FLUSH_BUFFERS
:
1118 DPRINT1("Flush request\n");
1120 ASSERT(FALSE
); // while (TRUE);
1128 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1130 ASSERT(FALSE
); // while (TRUE);
1137 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1138 Irp
->IoStatus
.Status
= Status
;
1139 Irp
->IoStatus
.Information
= 0;
1140 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1147 Irp
->IoStatus
.Status
= Status
;
1148 Irp
->IoStatus
.Information
= 0;
1149 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1154 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1157 PIO_WORKITEM WorkItem
;
1160 // Mark the IRP pending
1162 IoMarkIrpPending(Irp
);
1165 // Allocate a work item
1167 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1173 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1174 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1175 return STATUS_PENDING
;
1182 return STATUS_INSUFFICIENT_RESOURCES
;
1188 RamdiskReadWriteReal(IN PIRP Irp
,
1189 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1192 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1193 PIO_STACK_LOCATION IoStackLocation
;
1194 LARGE_INTEGER CurrentOffset
;
1195 ULONG BytesRead
, BytesLeft
, CopyLength
;
1196 PVOID Source
, Destination
;
1200 // Get the MDL and check if it's mapped
1202 Mdl
= Irp
->MdlAddress
;
1203 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
1206 // Use the mapped address
1208 SystemVa
= Mdl
->MappedSystemVa
;
1215 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1220 NormalPagePriority
);
1224 // Make sure we were able to map it
1226 CurrentBase
= SystemVa
;
1227 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1230 // Initialize default
1232 Irp
->IoStatus
.Information
= 0;
1235 // Get the I/O Stack Location and capture the data
1237 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1238 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1239 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1240 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1250 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1254 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1257 // Update our lengths
1259 Irp
->IoStatus
.Information
+= BytesRead
;
1260 CopyLength
= BytesRead
;
1263 // Check if this was a read or write
1265 Status
= STATUS_SUCCESS
;
1266 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1269 // Set our copy parameters
1271 Destination
= CurrentBase
;
1272 Source
= BaseAddress
;
1275 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1278 // Set our copy parameters
1280 Destination
= BaseAddress
;
1281 Source
= CurrentBase
;
1286 RtlCopyMemory(Destination
, Source
, CopyLength
);
1291 // Prepare us for failure
1293 BytesLeft
= CopyLength
;
1294 Status
= STATUS_INVALID_PARAMETER
;
1300 RamdiskUnmapPages(DeviceExtension
,
1306 // Update offset and bytes left
1308 BytesLeft
-= BytesRead
;
1309 CurrentOffset
.QuadPart
+= BytesRead
;
1310 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1313 // Check if we're done
1315 if (!BytesLeft
) return Status
;
1321 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1327 Irp
->IoStatus
.Information
= 1;
1328 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1329 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1330 return STATUS_SUCCESS
;
1335 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1338 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1340 //LARGE_INTEGER ByteOffset;
1341 PIO_STACK_LOCATION IoStackLocation
;
1342 NTSTATUS Status
, ReturnStatus
;
1345 // Get the device extension and make sure this isn't a bus
1347 DeviceExtension
= DeviceObject
->DeviceExtension
;
1348 if (DeviceExtension
->Type
== RamdiskBus
)
1353 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1358 // Capture parameters
1360 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1361 //Length = IoStackLocation->Parameters.Read.Length;
1362 //ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
1365 // FIXME: Validate offset
1369 // FIXME: Validate sector
1375 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1376 (DeviceExtension
->DiskOptions
.Readonly
))
1379 // Fail, this is read-only
1381 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1386 // See if we want to do this sync or async
1388 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1393 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1398 // Queue it to the worker
1400 Status
= SendIrpToThread(DeviceObject
, Irp
);
1401 ReturnStatus
= STATUS_PENDING
;
1404 // Check if we're pending or not
1406 if (Status
!= STATUS_PENDING
)
1412 Irp
->IoStatus
.Status
= Status
;
1413 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1414 ReturnStatus
= Status
;
1420 return ReturnStatus
;
1425 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1429 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1430 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1431 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1434 PDISK_GEOMETRY DiskGeometry
;
1437 // Grab the remove lock
1439 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1440 if (!NT_SUCCESS(Status
))
1445 Irp
->IoStatus
.Information
= 0;
1446 Irp
->IoStatus
.Status
= Status
;
1447 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1452 // Setup some defaults
1454 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1458 // Check if this is an bus device or the drive
1460 if (DeviceExtension
->Type
== RamdiskBus
)
1463 // Check what the request is
1465 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1468 // Request to create a ramdisk
1470 case FSCTL_CREATE_RAM_DISK
:
1475 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1476 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1482 // We don't handle anything else yet
1484 ASSERT(FALSE
); // while (TRUE);
1490 // Check what the request is
1492 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1494 case IOCTL_DISK_CHECK_VERIFY
:
1495 case IOCTL_STORAGE_CHECK_VERIFY
:
1496 case IOCTL_STORAGE_CHECK_VERIFY2
:
1497 case IOCTL_CDROM_CHECK_VERIFY
:
1500 ASSERT(FALSE
); // while (TRUE);
1503 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1504 case IOCTL_DISK_GET_MEDIA_TYPES
:
1505 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1506 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1509 // Validate the length
1511 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1512 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1517 Status
= STATUS_BUFFER_TOO_SMALL
;
1524 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1525 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1526 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1527 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1528 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1529 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1530 FixedMedia
: RemovableMedia
;
1535 Status
= STATUS_SUCCESS
;
1536 Information
= sizeof(DISK_GEOMETRY
);
1540 // Hack to support ReactOS's broken CDFS
1542 case IOCTL_CDROM_GET_LAST_SESSION
:
1545 // Validate the length
1547 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1548 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1553 Status
= STATUS_BUFFER_TOO_SMALL
;
1560 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1562 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1563 Toc
->FirstTrack
= 1;
1565 Toc
->TrackData
[0].Adr
= 1;
1566 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1567 Toc
->TrackData
[0].TrackNumber
= 1;
1568 Toc
->TrackData
[0].Address
[0] =
1569 Toc
->TrackData
[0].Address
[1] =
1570 Toc
->TrackData
[0].Address
[2] =
1571 Toc
->TrackData
[0].Address
[3] = 0;
1576 Status
= STATUS_SUCCESS
;
1577 Information
= RAMDISK_SESSION_SIZE
;
1580 case IOCTL_CDROM_READ_TOC
:
1583 // Validate the length
1585 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1586 OutputBufferLength
< sizeof(CDROM_TOC
))
1591 Status
= STATUS_BUFFER_TOO_SMALL
;
1598 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1599 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1605 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1606 Toc
->FirstTrack
= 1;
1608 Toc
->TrackData
[0].Adr
= 1;
1609 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1610 Toc
->TrackData
[0].TrackNumber
= 1;
1615 Status
= STATUS_SUCCESS
;
1616 Information
= RAMDISK_TOC_SIZE
;
1619 case IOCTL_DISK_SET_PARTITION_INFO
:
1621 Status
= RamdiskSetPartitionInfo(Irp
, DriveExtension
);
1624 case IOCTL_DISK_GET_PARTITION_INFO
:
1627 // Validate the length
1629 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1630 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1635 Status
= STATUS_BUFFER_TOO_SMALL
;
1640 // Check if we need to do this sync or async
1642 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1645 // Call the helper function
1647 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1652 // Do it asynchronously later
1660 Information
= Irp
->IoStatus
.Information
;
1663 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1666 ASSERT(FALSE
); // while (TRUE);
1669 case IOCTL_DISK_GET_LENGTH_INFO
:
1672 ASSERT(FALSE
); // while (TRUE);
1675 case IOCTL_DISK_IS_WRITABLE
:
1678 ASSERT(FALSE
); // while (TRUE);
1681 case IOCTL_SCSI_MINIPORT
:
1684 ASSERT(FALSE
); // while (TRUE);
1687 case IOCTL_STORAGE_QUERY_PROPERTY
:
1690 ASSERT(FALSE
); // while (TRUE);
1693 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1696 ASSERT(FALSE
); // while (TRUE);
1699 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1702 ASSERT(FALSE
); // while (TRUE);
1705 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1708 ASSERT(FALSE
); // while (TRUE);
1711 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1714 ASSERT(FALSE
); // while (TRUE);
1717 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1720 ASSERT(FALSE
); // while (TRUE);
1723 case IOCTL_VOLUME_OFFLINE
:
1726 ASSERT(FALSE
); // while (TRUE);
1732 // Drive code not emulated
1734 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1739 // If requests drop down here, we just return them complete them
1741 goto CompleteRequest
;
1745 // Queue the request to our worker thread
1748 Status
= SendIrpToThread(DeviceObject
, Irp
);
1754 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1755 if (Status
!= STATUS_PENDING
)
1758 // Complete the request
1760 Irp
->IoStatus
.Status
= Status
;
1761 Irp
->IoStatus
.Information
= Information
;
1762 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1773 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1774 IN PDEVICE_OBJECT DeviceObject
,
1777 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1778 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1779 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1780 ULONG Count
, DiskCount
, FinalCount
;
1781 PLIST_ENTRY ListHead
, NextEntry
;
1782 PDEVICE_OBJECT
* DriveDeviceObject
;
1783 RAMDISK_DEVICE_STATE State
;
1786 // Get the device extension and check if this is a drive
1788 DeviceExtension
= DeviceObject
->DeviceExtension
;
1789 if (DeviceExtension
->Type
== RamdiskDrive
)
1795 ASSERT(FALSE
); // while (TRUE);
1799 // Anything but bus relations, we don't handle
1801 if (Type
) goto PassToNext
;
1804 // Acquire the disk list lock
1806 KeEnterCriticalRegion();
1807 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1810 // Did a device already fill relations?
1812 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1813 if (DeviceRelations
)
1818 Count
= DeviceRelations
->Count
;
1829 // Now loop our drives
1832 ListHead
= &DeviceExtension
->DiskList
;
1833 NextEntry
= ListHead
->Flink
;
1834 while (NextEntry
!= ListHead
)
1837 // As long as it wasn't removed, count it in
1839 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1840 RAMDISK_DRIVE_EXTENSION
,
1842 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1845 // Move to the next one
1847 NextEntry
= NextEntry
->Flink
;
1851 // Now we know our final count
1853 FinalCount
= Count
+ DiskCount
;
1856 // Allocate the structure
1858 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1859 FIELD_OFFSET(DEVICE_RELATIONS
,
1862 sizeof(PDEVICE_OBJECT
),
1864 if (!OurDeviceRelations
)
1869 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1870 KeLeaveCriticalRegion();
1871 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1872 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1873 return STATUS_INSUFFICIENT_RESOURCES
;
1877 // Check if we already had some relations
1884 RtlCopyMemory(OurDeviceRelations
->Objects
,
1885 DeviceRelations
->Objects
,
1886 Count
* sizeof(PDEVICE_OBJECT
));
1892 OurDeviceRelations
->Count
= FinalCount
;
1895 // Now loop our drives again
1897 ListHead
= &DeviceExtension
->DiskList
;
1898 NextEntry
= ListHead
->Flink
;
1899 while (NextEntry
!= ListHead
)
1902 // Go to the end of the list
1904 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1907 // Get the drive state
1909 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1910 RAMDISK_DRIVE_EXTENSION
,
1912 State
= DriveExtension
->State
;
1915 // If it was removed or enumerated, we don't touch the device object
1917 if (State
>= RamdiskStateBusRemoved
)
1920 // If it was removed, we still have to keep track of this though
1922 if (State
== RamdiskStateBusRemoved
)
1925 // Mark it as enumerated now, but don't actually reference it
1927 DriveExtension
->State
= RamdiskStateEnumerated
;
1933 // First time it's enumerated, reference the device object
1935 ObReferenceObject(DriveExtension
->DeviceObject
);
1938 // Save the object pointer, and move on
1940 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1943 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1946 // Move to the next one
1948 NextEntry
= NextEntry
->Flink
;
1954 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1955 KeLeaveCriticalRegion();
1958 // Cleanup old relations
1960 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1965 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1966 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1969 // Pass to the next driver
1972 IoCopyCurrentIrpStackLocationToNext(Irp
);
1973 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1978 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject
,
1982 ASSERT(FALSE
); // while (TRUE);
1983 return STATUS_SUCCESS
;
1988 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject
,
1992 PLIST_ENTRY ListHead
, NextEntry
;
1993 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1994 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1996 DeviceExtension
= DeviceObject
->DeviceExtension
;
1999 // Acquire disks list lock
2001 KeEnterCriticalRegion();
2002 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
2007 ListHead
= &DeviceExtension
->DiskList
;
2008 NextEntry
= ListHead
->Flink
;
2009 while (NextEntry
!= ListHead
)
2011 DriveExtension
= CONTAINING_RECORD(NextEntry
,
2012 RAMDISK_DRIVE_EXTENSION
,
2018 IoAcquireRemoveLock(&DriveExtension
->RemoveLock
, NULL
);
2019 RamdiskDeleteDiskDevice(DriveExtension
->PhysicalDeviceObject
, NULL
);
2022 // RamdiskDeleteDiskDevice releases list lock, so reacquire it
2024 KeEnterCriticalRegion();
2025 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
2029 // Release disks list lock
2031 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
2032 KeLeaveCriticalRegion();
2035 // Prepare to pass to the lower driver
2037 IoSkipCurrentIrpStackLocation(Irp
);
2039 // Here everything went fine
2041 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2044 // Call lower driver
2046 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2051 DeviceExtension
->State
= RamdiskStateBusRemoved
;
2054 // Release the lock, and ensure that everyone
2055 // has finished its job before we continue
2056 // The lock has been acquired by the dispatcher
2058 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, Irp
);
2061 // If there's a drive name
2063 if (DeviceExtension
->DriveDeviceName
.Buffer
)
2066 // Inform it's going to be disabled
2067 // and free the drive name
2069 IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, FALSE
);
2070 RtlFreeUnicodeString(&DeviceExtension
->DriveDeviceName
);
2074 // Part from the stack, detach from lower device
2076 IoDetachDevice(DeviceExtension
->AttachedDevice
);
2079 // Finally, delete device
2081 RamdiskBusFdo
= NULL
;
2082 IoDeleteDevice(DeviceObject
);
2085 // Return status from lower driver
2092 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
2095 PIO_STACK_LOCATION IoStackLocation
;
2096 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2101 // Get the device extension and stack location
2103 DeviceExtension
= DeviceObject
->DeviceExtension
;
2104 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2105 Minor
= IoStackLocation
->MinorFunction
;
2108 // Check if the bus is removed
2110 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
2113 // Only remove-device and query-id are allowed
2115 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) && (Minor
!= IRP_MN_QUERY_ID
))
2118 // Fail anything else
2120 Status
= STATUS_NO_SUCH_DEVICE
;
2121 Irp
->IoStatus
.Status
= Status
;
2122 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2128 // Acquire the remove lock
2130 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2131 if (!NT_SUCCESS(Status
))
2136 Irp
->IoStatus
.Information
= 0;
2137 Irp
->IoStatus
.Status
= Status
;
2138 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2143 // Query the IRP type
2147 case IRP_MN_START_DEVICE
:
2149 DPRINT1("PnP IRP: %lx\n", Minor
);
2150 ASSERT(FALSE
); // while (TRUE);
2153 case IRP_MN_QUERY_STOP_DEVICE
:
2155 DPRINT1("PnP IRP: %lx\n", Minor
);
2156 ASSERT(FALSE
); // while (TRUE);
2159 case IRP_MN_CANCEL_STOP_DEVICE
:
2161 DPRINT1("PnP IRP: %lx\n", Minor
);
2162 ASSERT(FALSE
); // while (TRUE);
2165 case IRP_MN_STOP_DEVICE
:
2167 DPRINT1("PnP IRP: %lx\n", Minor
);
2168 ASSERT(FALSE
); // while (TRUE);
2171 case IRP_MN_QUERY_REMOVE_DEVICE
:
2173 DPRINT1("PnP IRP: %lx\n", Minor
);
2174 ASSERT(FALSE
); // while (TRUE);
2177 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2179 DPRINT1("PnP IRP: %lx\n", Minor
);
2180 ASSERT(FALSE
); // while (TRUE);
2183 case IRP_MN_REMOVE_DEVICE
:
2186 // Remove the proper device
2188 if (DeviceExtension
->Type
== RamdiskBus
)
2190 Status
= RamdiskRemoveBusDevice(DeviceObject
, Irp
);
2193 // Return here, lower device has already been called
2194 // And remove lock released. This is needed by the function.
2200 Status
= RamdiskDeleteDiskDevice(DeviceObject
, Irp
);
2203 // Complete the IRP here and return
2204 // Here again we don't have to release remove lock
2205 // This has already been done by the function.
2207 Irp
->IoStatus
.Status
= Status
;
2208 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2212 case IRP_MN_SURPRISE_REMOVAL
:
2214 DPRINT1("PnP IRP: %lx\n", Minor
);
2215 ASSERT(FALSE
); // while (TRUE);
2218 case IRP_MN_QUERY_ID
:
2223 if (DeviceExtension
->Type
== RamdiskDrive
)
2225 DPRINT1("PnP IRP: %lx\n", Minor
);
2226 ASSERT(FALSE
); // while (TRUE);
2230 case IRP_MN_QUERY_BUS_INFORMATION
:
2235 if (DeviceExtension
->Type
== RamdiskDrive
)
2237 DPRINT1("PnP IRP: %lx\n", Minor
);
2238 ASSERT(FALSE
); // while (TRUE);
2244 DPRINT1("PnP IRP: %lx\n", Minor
);
2245 ASSERT(FALSE
); // while (TRUE);
2248 case IRP_MN_QUERY_DEVICE_TEXT
:
2253 if (DeviceExtension
->Type
== RamdiskDrive
)
2255 DPRINT1("PnP IRP: %lx\n", Minor
);
2256 ASSERT(FALSE
); // while (TRUE);
2260 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2263 // Call our main routine
2265 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2267 QueryDeviceRelations
.Type
,
2270 goto ReleaseAndReturn
;
2272 case IRP_MN_QUERY_CAPABILITIES
:
2277 if (DeviceExtension
->Type
== RamdiskDrive
)
2279 DPRINT1("PnP IRP: %lx\n", Minor
);
2280 ASSERT(FALSE
); // while (TRUE);
2284 case IRP_MN_QUERY_RESOURCES
:
2285 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2288 // Complete immediately without touching it
2290 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2291 goto ReleaseAndReturn
;
2295 DPRINT1("Illegal IRP: %lx\n", Minor
);
2302 if (DeviceExtension
->Type
== RamdiskBus
)
2305 // Do we have an attached device?
2307 if (DeviceExtension
->AttachedDevice
)
2312 IoSkipCurrentIrpStackLocation(Irp
);
2313 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2318 // Release the lock and return status
2321 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2327 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2331 PIO_STACK_LOCATION IoStackLocation
;
2332 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2334 DeviceExtension
= DeviceObject
->DeviceExtension
;
2337 // If we have a device extension, take extra caution
2338 // with the lower driver
2340 if (DeviceExtension
!= NULL
)
2342 PoStartNextPowerIrp(Irp
);
2345 // Device has not been removed yet, so
2346 // pass to the attached/lower driver
2348 if (DeviceExtension
->State
< RamdiskStateBusRemoved
)
2350 IoSkipCurrentIrpStackLocation(Irp
);
2351 return PoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2354 // Otherwise, simply complete the IRP
2355 // Notifying that deletion is pending
2359 Irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
2360 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2361 return STATUS_DELETE_PENDING
;
2366 // Get stack and deal with minor functions
2368 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2369 switch (IoStackLocation
->MinorFunction
)
2371 case IRP_MN_SET_POWER
:
2373 // If setting device power state
2374 // it's all fine and return success
2376 if (DevicePowerState
)
2378 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2382 // Get appropriate status for return
2384 Status
= Irp
->IoStatus
.Status
;
2385 PoStartNextPowerIrp(Irp
);
2386 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2389 case IRP_MN_QUERY_POWER
:
2391 // We can obviously accept all states
2392 // So just return success
2395 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2396 PoStartNextPowerIrp(Irp
);
2397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2402 // Just complete and save status for return
2404 Status
= Irp
->IoStatus
.Status
;
2405 PoStartNextPowerIrp(Irp
);
2406 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2415 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2419 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2421 DeviceExtension
= DeviceObject
->DeviceExtension
;
2424 // If we have a device extension, forward the IRP
2425 // to the attached device
2427 if (DeviceExtension
!= NULL
)
2429 IoSkipCurrentIrpStackLocation(Irp
);
2430 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2433 // Otherwise just complete the request
2434 // And return the status with which we complete it
2438 Status
= Irp
->IoStatus
.Status
;
2439 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2447 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2451 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2453 DeviceExtension
= DeviceObject
->DeviceExtension
;
2456 // Having a proper device is mandatory
2458 if (DeviceExtension
->State
> RamdiskStateStopped
)
2460 Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2465 // Acquire the remove lock
2467 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2468 if (!NT_SUCCESS(Status
))
2474 // Queue the IRP for worker
2476 Status
= SendIrpToThread(DeviceObject
, Irp
);
2477 if (Status
!= STATUS_PENDING
)
2483 // Release the remove lock
2485 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2489 Irp
->IoStatus
.Information
= 0;
2490 Irp
->IoStatus
.Status
= Status
;
2491 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2499 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2503 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
2505 DeviceExtension
= DeviceObject
->DeviceExtension
;
2508 // Ensure we have drive extension
2509 // Only perform flush on disks that have been created
2510 // from registry entries
2512 if (DeviceExtension
->Type
!= RamdiskDrive
||
2513 DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
2515 Irp
->IoStatus
.Information
= 0;
2516 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2517 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2518 return STATUS_SUCCESS
;
2522 // Queue the IRP for worker
2524 Status
= SendIrpToThread(DeviceObject
, Irp
);
2525 if (Status
!= STATUS_PENDING
)
2528 // Queueing failed - complete the IRP
2529 // and return failure
2531 Irp
->IoStatus
.Information
= 0;
2532 Irp
->IoStatus
.Status
= Status
;
2533 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2541 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2544 // Just release registry path if previously allocated
2546 if (DriverRegistryPath
.Buffer
)
2548 ExFreePoolWithTag(DriverRegistryPath
.Buffer
, 'dmaR');
2554 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2555 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2557 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2558 PDEVICE_OBJECT AttachedDevice
;
2560 UNICODE_STRING DeviceName
;
2561 PDEVICE_OBJECT DeviceObject
;
2564 // Only create the bus FDO once
2566 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2569 // Create the bus FDO
2571 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2572 Status
= IoCreateDevice(DriverObject
,
2573 sizeof(RAMDISK_BUS_EXTENSION
),
2575 FILE_DEVICE_BUS_EXTENDER
,
2576 FILE_DEVICE_SECURE_OPEN
,
2579 if (NT_SUCCESS(Status
))
2582 // Initialize the bus FDO extension
2584 DeviceExtension
= DeviceObject
->DeviceExtension
;
2585 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2586 sizeof(RAMDISK_BUS_EXTENSION
));
2589 // Set bus FDO flags
2591 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2594 // Setup the bus FDO extension
2596 DeviceExtension
->Type
= RamdiskBus
;
2597 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2598 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2602 InitializeListHead(&DeviceExtension
->DiskList
);
2603 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2604 DeviceExtension
->DeviceObject
= DeviceObject
;
2607 // Register the RAM disk device interface
2609 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2610 &RamdiskBusInterface
,
2612 &DeviceExtension
->BusDeviceName
);
2613 if (!NT_SUCCESS(Status
))
2618 IoDeleteDevice(DeviceObject
);
2623 // Attach us to the device stack
2625 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2626 PhysicalDeviceObject
);
2627 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2628 if (!AttachedDevice
)
2633 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2634 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2635 IoDeleteDevice(DeviceObject
);
2636 return STATUS_NO_SUCH_DEVICE
;
2640 // Bus FDO is initialized
2642 RamdiskBusFdo
= DeviceObject
;
2645 // Loop for loader block
2650 // Are we being booted from setup? Not yet supported
2652 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2658 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2659 Status
= STATUS_SUCCESS
;
2670 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2671 IN PUNICODE_STRING RegistryPath
)
2673 PCHAR BootDeviceName
, CommandLine
;
2674 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2676 DPRINT("RAM Disk Driver Initialized\n");
2679 // Query ramdisk parameters
2681 QueryParameters(RegistryPath
);
2684 // Save the registry path
2686 DriverRegistryPath
= *RegistryPath
;
2687 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2688 RegistryPath
->Length
+
2691 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2692 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2695 // Set device routines
2697 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2698 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2699 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2700 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2701 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2702 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2703 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2704 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2705 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2706 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2707 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2708 DriverObject
->DriverUnload
= RamdiskUnload
;
2711 // Check for a loader block
2716 // Get the boot device name
2718 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2722 // Check if we're booting from ramdisk
2724 if ((strlen(BootDeviceName
) >= 10) &&
2725 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2728 // We'll have to tell the PnP Manager
2730 ReportDetectedDevice
= TRUE
;
2733 // Check for a command line
2735 CommandLine
= KeLoaderBlock
->LoadOptions
;
2739 // Check if this is an ISO boot
2741 if (strstr(CommandLine
, "RDEXPORTASCD"))
2744 // Remember for later
2746 ExportBootDiskAsCd
= TRUE
;
2750 // Check if this is PE boot
2752 if (strstr(CommandLine
, "MININT"))
2755 // Remember for later
2766 // Installing from Ramdisk isn't supported yet
2768 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2771 // Are we reporting the device
2773 if (ReportDetectedDevice
)
2778 Status
= IoReportDetectedDevice(DriverObject
,
2779 InterfaceTypeUndefined
,
2785 &PhysicalDeviceObject
);
2786 if (NT_SUCCESS(Status
))
2789 // Create the device object
2791 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2792 if (NT_SUCCESS(Status
))
2797 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2798 Status
= STATUS_SUCCESS
;
2807 Status
= STATUS_SUCCESS
;