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
;
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");
1074 case IOCTL_DISK_GET_PARTITION_INFO
:
1076 Status
= RamdiskGetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
1081 DPRINT1("Invalid request\n");
1093 // Read or write request
1098 DPRINT1("Read/Write request\n");
1104 // Internal request (SCSI?)
1106 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1108 DPRINT1("SCSI request\n");
1116 case IRP_MJ_FLUSH_BUFFERS
:
1118 DPRINT1("Flush request\n");
1128 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
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
1491 // Check what the request is
1493 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1495 case IOCTL_DISK_CHECK_VERIFY
:
1496 case IOCTL_STORAGE_CHECK_VERIFY
:
1497 case IOCTL_STORAGE_CHECK_VERIFY2
:
1498 case IOCTL_CDROM_CHECK_VERIFY
:
1504 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1505 case IOCTL_DISK_GET_MEDIA_TYPES
:
1506 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1507 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1510 // Validate the length
1512 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1513 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1518 Status
= STATUS_BUFFER_TOO_SMALL
;
1525 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1526 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1527 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1528 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1529 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1530 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1531 FixedMedia
: RemovableMedia
;
1536 Status
= STATUS_SUCCESS
;
1537 Information
= sizeof(DISK_GEOMETRY
);
1541 // Hack to support ReactOS's broken CDFS
1543 case IOCTL_CDROM_GET_LAST_SESSION
:
1546 // Validate the length
1548 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1549 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1554 Status
= STATUS_BUFFER_TOO_SMALL
;
1561 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1563 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1564 Toc
->FirstTrack
= 1;
1566 Toc
->TrackData
[0].Adr
= 1;
1567 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1568 Toc
->TrackData
[0].TrackNumber
= 1;
1569 Toc
->TrackData
[0].Address
[0] =
1570 Toc
->TrackData
[0].Address
[1] =
1571 Toc
->TrackData
[0].Address
[2] =
1572 Toc
->TrackData
[0].Address
[3] = 0;
1577 Status
= STATUS_SUCCESS
;
1578 Information
= RAMDISK_SESSION_SIZE
;
1581 case IOCTL_CDROM_READ_TOC
:
1584 // Validate the length
1586 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1587 OutputBufferLength
< sizeof(CDROM_TOC
))
1592 Status
= STATUS_BUFFER_TOO_SMALL
;
1599 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1600 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1606 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1607 Toc
->FirstTrack
= 1;
1609 Toc
->TrackData
[0].Adr
= 1;
1610 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1611 Toc
->TrackData
[0].TrackNumber
= 1;
1616 Status
= STATUS_SUCCESS
;
1617 Information
= RAMDISK_TOC_SIZE
;
1620 case IOCTL_DISK_SET_PARTITION_INFO
:
1622 Status
= RamdiskSetPartitionInfo(Irp
, DriveExtension
);
1625 case IOCTL_DISK_GET_PARTITION_INFO
:
1628 // Validate the length
1630 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1631 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1636 Status
= STATUS_BUFFER_TOO_SMALL
;
1641 // Check if we need to do this sync or async
1643 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1646 // Call the helper function
1648 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1653 // Do it asynchronously later
1661 Information
= Irp
->IoStatus
.Information
;
1664 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1670 case IOCTL_DISK_GET_LENGTH_INFO
:
1676 case IOCTL_DISK_IS_WRITABLE
:
1682 case IOCTL_SCSI_MINIPORT
:
1688 case IOCTL_STORAGE_QUERY_PROPERTY
:
1694 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1700 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1706 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1712 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1718 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1724 case IOCTL_VOLUME_OFFLINE
:
1733 // Drive code not emulated
1735 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1740 // If requests drop down here, we just return them complete them
1742 goto CompleteRequest
;
1746 // Queue the request to our worker thread
1749 Status
= SendIrpToThread(DeviceObject
, Irp
);
1755 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1756 if (Status
!= STATUS_PENDING
)
1759 // Complete the request
1761 Irp
->IoStatus
.Status
= Status
;
1762 Irp
->IoStatus
.Information
= Information
;
1763 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1774 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1775 IN PDEVICE_OBJECT DeviceObject
,
1778 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1779 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1780 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1781 ULONG Count
, DiskCount
, FinalCount
;
1782 PLIST_ENTRY ListHead
, NextEntry
;
1783 PDEVICE_OBJECT
* DriveDeviceObject
;
1784 RAMDISK_DEVICE_STATE State
;
1787 // Get the device extension and check if this is a drive
1789 DeviceExtension
= DeviceObject
->DeviceExtension
;
1790 if (DeviceExtension
->Type
== RamdiskDrive
)
1800 // Anything but bus relations, we don't handle
1802 if (Type
) goto PassToNext
;
1805 // Acquire the disk list lock
1807 KeEnterCriticalRegion();
1808 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1811 // Did a device already fill relations?
1813 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1814 if (DeviceRelations
)
1819 Count
= DeviceRelations
->Count
;
1830 // Now loop our drives
1833 ListHead
= &DeviceExtension
->DiskList
;
1834 NextEntry
= ListHead
->Flink
;
1835 while (NextEntry
!= ListHead
)
1838 // As long as it wasn't removed, count it in
1840 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1841 RAMDISK_DRIVE_EXTENSION
,
1843 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1846 // Move to the next one
1848 NextEntry
= NextEntry
->Flink
;
1852 // Now we know our final count
1854 FinalCount
= Count
+ DiskCount
;
1857 // Allocate the structure
1859 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1860 FIELD_OFFSET(DEVICE_RELATIONS
,
1863 sizeof(PDEVICE_OBJECT
),
1865 if (!OurDeviceRelations
)
1870 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1871 KeLeaveCriticalRegion();
1872 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1873 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1874 return STATUS_INSUFFICIENT_RESOURCES
;
1878 // Check if we already had some relations
1885 RtlCopyMemory(OurDeviceRelations
->Objects
,
1886 DeviceRelations
->Objects
,
1887 Count
* sizeof(PDEVICE_OBJECT
));
1893 OurDeviceRelations
->Count
= FinalCount
;
1896 // Now loop our drives again
1898 ListHead
= &DeviceExtension
->DiskList
;
1899 NextEntry
= ListHead
->Flink
;
1900 while (NextEntry
!= ListHead
)
1903 // Go to the end of the list
1905 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1908 // Get the drive state
1910 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1911 RAMDISK_DRIVE_EXTENSION
,
1913 State
= DriveExtension
->State
;
1916 // If it was removed or enumerated, we don't touch the device object
1918 if (State
>= RamdiskStateBusRemoved
)
1921 // If it was removed, we still have to keep track of this though
1923 if (State
== RamdiskStateBusRemoved
)
1926 // Mark it as enumerated now, but don't actually reference it
1928 DriveExtension
->State
= RamdiskStateEnumerated
;
1934 // First time it's enumerated, reference the device object
1936 ObReferenceObject(DriveExtension
->DeviceObject
);
1939 // Save the object pointer, and move on
1941 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1944 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1947 // Move to the next one
1949 NextEntry
= NextEntry
->Flink
;
1955 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1956 KeLeaveCriticalRegion();
1959 // Cleanup old relations
1961 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1966 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1967 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1970 // Pass to the next driver
1973 IoCopyCurrentIrpStackLocationToNext(Irp
);
1974 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1979 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject
,
1984 return STATUS_SUCCESS
;
1989 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject
,
1993 PLIST_ENTRY ListHead
, NextEntry
;
1994 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1995 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1997 DeviceExtension
= DeviceObject
->DeviceExtension
;
2000 // Acquire disks list lock
2002 KeEnterCriticalRegion();
2003 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
2008 ListHead
= &DeviceExtension
->DiskList
;
2009 NextEntry
= ListHead
->Flink
;
2010 while (NextEntry
!= ListHead
)
2012 DriveExtension
= CONTAINING_RECORD(NextEntry
,
2013 RAMDISK_DRIVE_EXTENSION
,
2019 IoAcquireRemoveLock(&DriveExtension
->RemoveLock
, NULL
);
2020 RamdiskDeleteDiskDevice(DriveExtension
->PhysicalDeviceObject
, NULL
);
2023 // RamdiskDeleteDiskDevice releases list lock, so reacquire it
2025 KeEnterCriticalRegion();
2026 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
2030 // Release disks list lock
2032 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
2033 KeLeaveCriticalRegion();
2036 // Prepare to pass to the lower driver
2038 IoSkipCurrentIrpStackLocation(Irp
);
2040 // Here everything went fine
2042 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2045 // Call lower driver
2047 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2052 DeviceExtension
->State
= RamdiskStateBusRemoved
;
2055 // Release the lock, and ensure that everyone
2056 // has finished its job before we continue
2057 // The lock has been acquired by the dispatcher
2059 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, Irp
);
2062 // If there's a drive name
2064 if (DeviceExtension
->DriveDeviceName
.Buffer
)
2067 // Inform it's going to be disabled
2068 // and free the drive name
2070 IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, FALSE
);
2071 RtlFreeUnicodeString(&DeviceExtension
->DriveDeviceName
);
2075 // Part from the stack, detach from lower device
2077 IoDetachDevice(DeviceExtension
->AttachedDevice
);
2080 // Finally, delete device
2082 RamdiskBusFdo
= NULL
;
2083 IoDeleteDevice(DeviceObject
);
2086 // Return status from lower driver
2093 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
2096 PIO_STACK_LOCATION IoStackLocation
;
2097 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2102 // Get the device extension and stack location
2104 DeviceExtension
= DeviceObject
->DeviceExtension
;
2105 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2106 Minor
= IoStackLocation
->MinorFunction
;
2109 // Check if the bus is removed
2111 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
2114 // Only remove-device and query-id are allowed
2116 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) && (Minor
!= IRP_MN_QUERY_ID
))
2119 // Fail anything else
2121 Status
= STATUS_NO_SUCH_DEVICE
;
2122 Irp
->IoStatus
.Status
= Status
;
2123 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2129 // Acquire the remove lock
2131 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2132 if (!NT_SUCCESS(Status
))
2137 Irp
->IoStatus
.Information
= 0;
2138 Irp
->IoStatus
.Status
= Status
;
2139 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2144 // Query the IRP type
2148 case IRP_MN_START_DEVICE
:
2150 DPRINT1("PnP IRP: %lx\n", Minor
);
2154 case IRP_MN_QUERY_STOP_DEVICE
:
2156 DPRINT1("PnP IRP: %lx\n", Minor
);
2160 case IRP_MN_CANCEL_STOP_DEVICE
:
2162 DPRINT1("PnP IRP: %lx\n", Minor
);
2166 case IRP_MN_STOP_DEVICE
:
2168 DPRINT1("PnP IRP: %lx\n", Minor
);
2172 case IRP_MN_QUERY_REMOVE_DEVICE
:
2174 DPRINT1("PnP IRP: %lx\n", Minor
);
2178 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2180 DPRINT1("PnP IRP: %lx\n", Minor
);
2184 case IRP_MN_REMOVE_DEVICE
:
2187 // Remove the proper device
2189 if (DeviceExtension
->Type
== RamdiskBus
)
2191 Status
= RamdiskRemoveBusDevice(DeviceObject
, Irp
);
2194 // Return here, lower device has already been called
2195 // And remove lock released. This is needed by the function.
2201 Status
= RamdiskDeleteDiskDevice(DeviceObject
, Irp
);
2204 // Complete the IRP here and return
2205 // Here again we don't have to release remove lock
2206 // This has already been done by the function.
2208 Irp
->IoStatus
.Status
= Status
;
2209 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2213 case IRP_MN_SURPRISE_REMOVAL
:
2215 DPRINT1("PnP IRP: %lx\n", Minor
);
2219 case IRP_MN_QUERY_ID
:
2224 if (DeviceExtension
->Type
== RamdiskDrive
)
2226 DPRINT1("PnP IRP: %lx\n", Minor
);
2231 case IRP_MN_QUERY_BUS_INFORMATION
:
2236 if (DeviceExtension
->Type
== RamdiskDrive
)
2238 DPRINT1("PnP IRP: %lx\n", Minor
);
2245 DPRINT1("PnP IRP: %lx\n", Minor
);
2249 case IRP_MN_QUERY_DEVICE_TEXT
:
2254 if (DeviceExtension
->Type
== RamdiskDrive
)
2256 DPRINT1("PnP IRP: %lx\n", Minor
);
2261 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2264 // Call our main routine
2266 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2268 QueryDeviceRelations
.Type
,
2271 goto ReleaseAndReturn
;
2273 case IRP_MN_QUERY_CAPABILITIES
:
2278 if (DeviceExtension
->Type
== RamdiskDrive
)
2280 DPRINT1("PnP IRP: %lx\n", Minor
);
2285 case IRP_MN_QUERY_RESOURCES
:
2286 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2289 // Complete immediately without touching it
2291 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2292 goto ReleaseAndReturn
;
2296 DPRINT1("Illegal IRP: %lx\n", Minor
);
2303 if (DeviceExtension
->Type
== RamdiskBus
)
2306 // Do we have an attached device?
2308 if (DeviceExtension
->AttachedDevice
)
2313 IoSkipCurrentIrpStackLocation(Irp
);
2314 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2319 // Release the lock and return status
2322 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2328 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2332 PIO_STACK_LOCATION IoStackLocation
;
2333 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2335 DeviceExtension
= DeviceObject
->DeviceExtension
;
2338 // If we have a device extension, take extra caution
2339 // with the lower driver
2341 if (DeviceExtension
!= NULL
)
2343 PoStartNextPowerIrp(Irp
);
2346 // Device has not been removed yet, so
2347 // pass to the attached/lower driver
2349 if (DeviceExtension
->State
< RamdiskStateBusRemoved
)
2351 IoSkipCurrentIrpStackLocation(Irp
);
2352 return PoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2355 // Otherwise, simply complete the IRP
2356 // Notifying that deletion is pending
2360 Irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
2361 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2362 return STATUS_DELETE_PENDING
;
2367 // Get stack and deal with minor functions
2369 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2370 switch (IoStackLocation
->MinorFunction
)
2372 case IRP_MN_SET_POWER
:
2374 // If setting device power state
2375 // it's all fine and return success
2377 if (DevicePowerState
)
2379 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2383 // Get appropriate status for return
2385 Status
= Irp
->IoStatus
.Status
;
2386 PoStartNextPowerIrp(Irp
);
2387 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2390 case IRP_MN_QUERY_POWER
:
2392 // We can obviously accept all states
2393 // So just return success
2396 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2397 PoStartNextPowerIrp(Irp
);
2398 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2403 // Just complete and save status for return
2405 Status
= Irp
->IoStatus
.Status
;
2406 PoStartNextPowerIrp(Irp
);
2407 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2416 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2420 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2422 DeviceExtension
= DeviceObject
->DeviceExtension
;
2425 // If we have a device extension, forward the IRP
2426 // to the attached device
2428 if (DeviceExtension
!= NULL
)
2430 IoSkipCurrentIrpStackLocation(Irp
);
2431 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2434 // Otherwise just complete the request
2435 // And return the status with which we complete it
2439 Status
= Irp
->IoStatus
.Status
;
2440 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2448 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2452 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2454 DeviceExtension
= DeviceObject
->DeviceExtension
;
2457 // Having a proper device is mandatory
2459 if (DeviceExtension
->State
> RamdiskStateStopped
)
2461 Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2466 // Acquire the remove lock
2468 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2469 if (!NT_SUCCESS(Status
))
2475 // Queue the IRP for worker
2477 Status
= SendIrpToThread(DeviceObject
, Irp
);
2478 if (Status
!= STATUS_PENDING
)
2484 // Release the remove lock
2486 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2490 Irp
->IoStatus
.Information
= 0;
2491 Irp
->IoStatus
.Status
= Status
;
2492 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2500 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2504 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
2506 DeviceExtension
= DeviceObject
->DeviceExtension
;
2509 // Ensure we have drive extension
2510 // Only perform flush on disks that have been created
2511 // from registry entries
2513 if (DeviceExtension
->Type
!= RamdiskDrive
||
2514 DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
2516 Irp
->IoStatus
.Information
= 0;
2517 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2518 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2519 return STATUS_SUCCESS
;
2523 // Queue the IRP for worker
2525 Status
= SendIrpToThread(DeviceObject
, Irp
);
2526 if (Status
!= STATUS_PENDING
)
2529 // Queueing failed - complete the IRP
2530 // and return failure
2532 Irp
->IoStatus
.Information
= 0;
2533 Irp
->IoStatus
.Status
= Status
;
2534 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2542 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2545 // Just release registry path if previously allocated
2547 if (DriverRegistryPath
.Buffer
)
2549 ExFreePoolWithTag(DriverRegistryPath
.Buffer
, 'dmaR');
2555 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2556 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2558 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2559 PDEVICE_OBJECT AttachedDevice
;
2561 UNICODE_STRING DeviceName
;
2562 PDEVICE_OBJECT DeviceObject
;
2565 // Only create the bus FDO once
2567 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2570 // Create the bus FDO
2572 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2573 Status
= IoCreateDevice(DriverObject
,
2574 sizeof(RAMDISK_BUS_EXTENSION
),
2576 FILE_DEVICE_BUS_EXTENDER
,
2577 FILE_DEVICE_SECURE_OPEN
,
2580 if (NT_SUCCESS(Status
))
2583 // Initialize the bus FDO extension
2585 DeviceExtension
= DeviceObject
->DeviceExtension
;
2586 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2587 sizeof(RAMDISK_BUS_EXTENSION
));
2590 // Set bus FDO flags
2592 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2595 // Setup the bus FDO extension
2597 DeviceExtension
->Type
= RamdiskBus
;
2598 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2599 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2603 InitializeListHead(&DeviceExtension
->DiskList
);
2604 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2605 DeviceExtension
->DeviceObject
= DeviceObject
;
2608 // Register the RAM disk device interface
2610 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2611 &RamdiskBusInterface
,
2613 &DeviceExtension
->BusDeviceName
);
2614 if (!NT_SUCCESS(Status
))
2619 IoDeleteDevice(DeviceObject
);
2624 // Attach us to the device stack
2626 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2627 PhysicalDeviceObject
);
2628 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2629 if (!AttachedDevice
)
2634 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2635 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2636 IoDeleteDevice(DeviceObject
);
2637 return STATUS_NO_SUCH_DEVICE
;
2641 // Bus FDO is initialized
2643 RamdiskBusFdo
= DeviceObject
;
2646 // Loop for loader block
2651 // Are we being booted from setup? Not yet supported
2653 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2659 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2660 Status
= STATUS_SUCCESS
;
2671 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2672 IN PUNICODE_STRING RegistryPath
)
2674 PCHAR BootDeviceName
, CommandLine
;
2675 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2677 DPRINT("RAM Disk Driver Initialized\n");
2680 // Query ramdisk parameters
2682 QueryParameters(RegistryPath
);
2685 // Save the registry path
2687 DriverRegistryPath
= *RegistryPath
;
2688 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2689 RegistryPath
->Length
+
2692 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2693 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2696 // Set device routines
2698 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2699 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2700 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2701 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2702 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2703 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2704 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2705 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2706 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2707 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2708 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2709 DriverObject
->DriverUnload
= RamdiskUnload
;
2712 // Check for a loader block
2717 // Get the boot device name
2719 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2723 // Check if we're booting from ramdisk
2725 if ((strlen(BootDeviceName
) >= 10) &&
2726 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2729 // We'll have to tell the PnP Manager
2731 ReportDetectedDevice
= TRUE
;
2734 // Check for a command line
2736 CommandLine
= KeLoaderBlock
->LoadOptions
;
2740 // Check if this is an ISO boot
2742 if (strstr(CommandLine
, "RDEXPORTASCD"))
2745 // Remember for later
2747 ExportBootDiskAsCd
= TRUE
;
2751 // Check if this is PE boot
2753 if (strstr(CommandLine
, "MININT"))
2756 // Remember for later
2767 // Installing from Ramdisk isn't supported yet
2769 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2772 // Are we reporting the device
2774 if (ReportDetectedDevice
)
2779 Status
= IoReportDetectedDevice(DriverObject
,
2780 InterfaceTypeUndefined
,
2786 &PhysicalDeviceObject
);
2787 if (NT_SUCCESS(Status
))
2790 // Create the device object
2792 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2793 if (NT_SUCCESS(Status
))
2798 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2799 Status
= STATUS_SUCCESS
;
2808 Status
= STATUS_SUCCESS
;