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
, ViewCount
, DiskType
, Length
;
408 PDEVICE_OBJECT DeviceObject
;
409 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
411 WCHAR LocalBuffer
[16];
412 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
413 PPACKED_BOOT_SECTOR BootSector
;
414 BIOS_PARAMETER_BLOCK BiosBlock
;
415 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
417 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
418 ULONG CylinderCount
, SizeByCylinders
;
421 // Check if we're a boot RAM disk
423 DiskType
= Input
->DiskType
;
424 if (DiskType
>= RAMDISK_BOOT_DISK
)
427 // Check if we're an ISO
429 if (DiskType
== RAMDISK_BOOT_DISK
)
432 // NTLDR mounted us somewhere
434 BasePage
= Input
->BasePage
;
435 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
438 // Sanitize disk options
440 Input
->Options
.Fixed
= TRUE
;
441 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
442 Input
->Options
.Readonly
;
443 Input
->Options
.Hidden
= FALSE
;
444 Input
->Options
.NoDosDevice
= FALSE
;
445 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
450 // The only other possibility is a WIM disk
452 if (DiskType
!= RAMDISK_WIM_DISK
)
457 return STATUS_INVALID_PARAMETER
;
461 // Read the view count instead
463 ViewCount
= Input
->ViewCount
;
466 // Sanitize disk options
468 Input
->Options
.Hidden
= FALSE
;
469 Input
->Options
.NoDosDevice
= FALSE
;
470 Input
->Options
.Readonly
= FALSE
;
471 Input
->Options
.NoDriveLetter
= TRUE
;
472 Input
->Options
.Fixed
= TRUE
;
476 // Are we just validating and returning to the user?
478 if (ValidateOnly
) return STATUS_SUCCESS
;
481 // Build the GUID string
483 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
484 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
489 Status
= STATUS_INSUFFICIENT_RESOURCES
;
494 // Allocate our device name
496 Length
= GuidString
.Length
+ 32;
497 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
505 Status
= STATUS_INSUFFICIENT_RESOURCES
;
510 // Build the device name string
512 DeviceName
.Buffer
= Buffer
;
513 DeviceName
.Length
= Length
- 2;
514 DeviceName
.MaximumLength
= Length
;
515 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
516 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
519 // Create the drive device
521 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
522 sizeof(RAMDISK_DRIVE_EXTENSION
),
524 (Input
->Options
.ExportAsCd
) ?
525 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
529 if (!NT_SUCCESS(Status
)) goto FailCreate
;
532 // Grab the drive extension
534 DriveExtension
= DeviceObject
->DeviceExtension
;
537 // Check if we need a DOS device
539 if (!Input
->Options
.NoDosDevice
)
542 // Build the symbolic link name
544 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
545 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
546 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
547 SymbolicLinkName
.MaximumLength
,
549 SymbolicLinkName
.Buffer
= Buffer
;
556 L
"\\GLOBAL??\\Ramdisk",
557 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
560 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
561 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
562 if (!NT_SUCCESS(Status
))
567 Input
->Options
.NoDosDevice
= TRUE
;
569 SymbolicLinkName
.Buffer
= NULL
;
577 Input
->Options
.NoDosDevice
= TRUE
;
581 // It this an ISO boot ramdisk?
583 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
586 // Does it need a drive letter?
588 if (!Input
->Options
.NoDriveLetter
)
591 // Build it and take over the existing symbolic link
593 _snwprintf(LocalBuffer
,
595 L
"\\DosDevices\\%wc:",
597 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
598 IoDeleteSymbolicLink(&DriveString
);
599 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
602 // Save the drive letter
604 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
611 // Setup the device object flags
613 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
614 DeviceObject
->AlignmentRequirement
= 1;
617 // Build the drive FDO
619 *NewDriveExtension
= DriveExtension
;
620 DriveExtension
->Type
= RamdiskDrive
;
621 DiskLength
= Input
->DiskLength
;
622 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
623 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
627 DriveExtension
->DriveDeviceName
= DeviceName
;
628 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
629 DriveExtension
->GuidString
= GuidString
;
630 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
631 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
632 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
633 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
634 DriveExtension
->DiskType
= Input
->DiskType
;
635 DriveExtension
->DiskOptions
= Input
->Options
;
636 DriveExtension
->DiskLength
= DiskLength
;
637 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
638 DriveExtension
->BasePage
= Input
->BasePage
;
639 DriveExtension
->BytesPerSector
= 0;
640 DriveExtension
->SectorsPerTrack
= 0;
641 DriveExtension
->NumberOfHeads
= 0;
644 // Make sure we don't free it later
646 DeviceName
.Buffer
= NULL
;
647 SymbolicLinkName
.Buffer
= NULL
;
648 GuidString
.Buffer
= NULL
;
651 // Check if this is an boot disk, or a registry ram drive
653 if (!(Input
->Options
.ExportAsCd
) &&
654 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
657 // Not an ISO boot, but it's a boot FS -- map it to figure out the
660 CurrentOffset
.QuadPart
= 0;
661 BaseAddress
= RamdiskMapPages(DriveExtension
,
670 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
671 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
672 BytesPerSector
= BiosBlock
.BytesPerSector
;
673 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
674 Heads
= BiosBlock
.Heads
;
679 DriveExtension
->BytesPerSector
= BytesPerSector
;
680 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
681 DriveExtension
->NumberOfHeads
= Heads
;
686 CurrentOffset
.QuadPart
= 0;
687 RamdiskUnmapPages(DriveExtension
,
697 Status
= STATUS_INSUFFICIENT_RESOURCES
;
703 // Check if the drive settings haven't been set yet
705 if ((DriveExtension
->BytesPerSector
== 0) ||
706 (DriveExtension
->SectorsPerTrack
== 0) ||
707 (DriveExtension
->NumberOfHeads
== 0))
710 // Check if this is a CD
712 if (Input
->Options
.ExportAsCd
)
715 // Setup partition parameters default for ISO 9660
717 DriveExtension
->BytesPerSector
= 2048;
718 DriveExtension
->SectorsPerTrack
= 32;
719 DriveExtension
->NumberOfHeads
= 64;
724 // Setup partition parameters default for FAT
726 DriveExtension
->BytesPerSector
= 512;
727 DriveExtension
->SectorsPerTrack
= 128;
728 DriveExtension
->NumberOfHeads
= 16;
733 // Calculate the cylinder size
735 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
736 DriveExtension
->SectorsPerTrack
*
737 DriveExtension
->NumberOfHeads
;
738 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
739 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
740 DriveExtension
->Cylinders
= CylinderCount
;
741 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
744 // Align cylinder size up
746 DriveExtension
->Cylinders
++;
750 // Acquire the disk lock
752 KeEnterCriticalRegion();
753 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
758 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
763 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
764 KeLeaveCriticalRegion();
769 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
770 return STATUS_SUCCESS
;
776 return STATUS_SUCCESS
;
781 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
783 IN BOOLEAN ValidateOnly
)
785 PRAMDISK_CREATE_INPUT Input
;
787 PRAMDISK_BUS_EXTENSION DeviceExtension
;
788 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
790 PWCHAR FileNameStart
, FileNameEnd
;
792 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
795 // Get the device extension and our input data
797 DeviceExtension
= DeviceObject
->DeviceExtension
;
798 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
799 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
802 // Validate input parameters
804 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
805 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
810 return STATUS_INVALID_PARAMETER
;
814 // Validate the disk type
816 DiskType
= Input
->DiskType
;
817 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
820 // Look at the disk type
822 if (DiskType
== RAMDISK_BOOT_DISK
)
825 // We only allow this as an early-init boot
827 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
830 // Save command-line flags
832 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
833 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
837 // Validate the disk type
839 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
842 // If the type isn't CDFS, it has to at least be raw CD
844 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
848 // Check if this is an actual file
850 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
853 // Validate the file name
855 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
856 FileNameEnd
= Input
->FileName
+ 1;
857 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
858 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
862 // Create the actual device
864 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
868 if (NT_SUCCESS(Status
))
871 // Invalidate and set success
873 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
874 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
885 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
888 PRAMDISK_BUS_EXTENSION DeviceExtension
;
890 PIO_STACK_LOCATION IoStackLocation
;
894 // Get the stack location
896 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
899 // Free the work item
901 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
904 // Grab the device extension and lock it
906 DeviceExtension
= DeviceObject
->DeviceExtension
;
907 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
908 if (NT_SUCCESS(Status
))
911 // Discriminate by major code
913 switch (IoStackLocation
->MajorFunction
)
918 case IRP_MJ_DEVICE_CONTROL
:
921 // Let's take a look at the IOCTL
923 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
926 // Ramdisk create request
928 case FSCTL_CREATE_RAM_DISK
:
931 // This time we'll do it for real
933 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
936 case IOCTL_DISK_SET_PARTITION_INFO
:
938 DPRINT1("Set partition info request\n");
943 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
945 DPRINT1("Get drive layout request\n");
950 case IOCTL_DISK_GET_PARTITION_INFO
:
952 DPRINT1("Get partitinon info request\n");
959 DPRINT1("Invalid request\n");
971 // Read or write request
976 DPRINT1("Read/Write request\n");
982 // Internal request (SCSI?)
984 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
986 DPRINT1("SCSI request\n");
994 case IRP_MJ_FLUSH_BUFFERS
:
996 DPRINT1("Flush request\n");
1006 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1015 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1016 Irp
->IoStatus
.Status
= Status
;
1017 Irp
->IoStatus
.Information
= 0;
1018 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1025 Irp
->IoStatus
.Status
= Status
;
1026 Irp
->IoStatus
.Information
= 0;
1027 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1032 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1035 PIO_WORKITEM WorkItem
;
1038 // Mark the IRP pending
1040 IoMarkIrpPending(Irp
);
1043 // Allocate a work item
1045 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1051 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1052 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1053 return STATUS_PENDING
;
1060 return STATUS_INSUFFICIENT_RESOURCES
;
1066 RamdiskReadWriteReal(IN PIRP Irp
,
1067 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1070 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1071 PIO_STACK_LOCATION IoStackLocation
;
1072 LARGE_INTEGER CurrentOffset
;
1073 ULONG BytesRead
, BytesLeft
, CopyLength
;
1074 PVOID Source
, Destination
;
1078 // Get the MDL and check if it's mapped
1080 Mdl
= Irp
->MdlAddress
;
1081 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
1084 // Use the mapped address
1086 SystemVa
= Mdl
->MappedSystemVa
;
1093 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1098 NormalPagePriority
);
1102 // Make sure we were able to map it
1104 CurrentBase
= SystemVa
;
1105 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1108 // Initialize default
1110 Irp
->IoStatus
.Information
= 0;
1113 // Get the I/O Stack Location and capture the data
1115 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1116 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1117 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1118 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1128 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1132 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1135 // Update our lengths
1137 Irp
->IoStatus
.Information
+= BytesRead
;
1138 CopyLength
= BytesRead
;
1141 // Check if this was a read or write
1143 Status
= STATUS_SUCCESS
;
1144 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1147 // Set our copy parameters
1149 Destination
= CurrentBase
;
1150 Source
= BaseAddress
;
1153 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1156 // Set our copy parameters
1158 Destination
= BaseAddress
;
1159 Source
= CurrentBase
;
1164 RtlCopyMemory(Destination
, Source
, CopyLength
);
1169 // Prepare us for failure
1171 BytesLeft
= CopyLength
;
1172 Status
= STATUS_INVALID_PARAMETER
;
1178 RamdiskUnmapPages(DeviceExtension
,
1184 // Update offset and bytes left
1186 BytesLeft
-= BytesRead
;
1187 CurrentOffset
.QuadPart
+= BytesRead
;
1188 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1191 // Check if we're done
1193 if (!BytesLeft
) return Status
;
1199 RamdiskGetPartitionInfo(IN PIRP Irp
,
1200 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1203 PPARTITION_INFORMATION PartitionInfo
;
1205 LARGE_INTEGER Zero
= {{0, 0}};
1207 PIO_STACK_LOCATION IoStackLocation
;
1210 // Validate the length
1212 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1213 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1214 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1219 Status
= STATUS_BUFFER_TOO_SMALL
;
1220 Irp
->IoStatus
.Status
= Status
;
1221 Irp
->IoStatus
.Information
= 0;
1226 // Map the partition table
1228 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
1234 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1235 Irp
->IoStatus
.Status
= Status
;
1236 Irp
->IoStatus
.Information
= 0;
1241 // Fill out the information
1243 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
1244 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
1245 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
1246 DeviceExtension
->SectorsPerTrack
*
1247 DeviceExtension
->NumberOfHeads
*
1248 DeviceExtension
->Cylinders
;
1249 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
1250 PartitionInfo
->PartitionNumber
= 0;
1251 PartitionInfo
->PartitionType
= PARTITION_FAT32
; //*((PCHAR)BaseAddress + 450);
1252 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
1253 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
1254 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
1256 PartitionInfo
->RewritePartition
= FALSE
;
1259 // Unmap the partition table
1261 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
1266 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1267 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
1268 return STATUS_SUCCESS
;
1273 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1279 Irp
->IoStatus
.Information
= 1;
1280 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1281 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1282 return STATUS_SUCCESS
;
1287 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1290 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1292 LARGE_INTEGER ByteOffset
;
1293 PIO_STACK_LOCATION IoStackLocation
;
1294 NTSTATUS Status
, ReturnStatus
;
1297 // Get the device extension and make sure this isn't a bus
1299 DeviceExtension
= DeviceObject
->DeviceExtension
;
1300 if (DeviceExtension
->Type
== RamdiskBus
)
1305 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1310 // Capture parameters
1312 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1313 Length
= IoStackLocation
->Parameters
.Read
.Length
;
1314 ByteOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1317 // FIXME: Validate offset
1321 // FIXME: Validate sector
1327 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1328 (DeviceExtension
->DiskOptions
.Readonly
))
1331 // Fail, this is read-only
1333 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1338 // See if we want to do this sync or async
1340 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1345 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1350 // Queue it to the worker
1352 Status
= SendIrpToThread(DeviceObject
, Irp
);
1353 ReturnStatus
= STATUS_PENDING
;
1356 // Check if we're pending or not
1358 if (Status
!= STATUS_PENDING
)
1364 Irp
->IoStatus
.Status
= Status
;
1365 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1366 ReturnStatus
= Status
;
1372 return ReturnStatus
;
1377 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1381 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1382 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1383 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1386 PDISK_GEOMETRY DiskGeometry
;
1389 // Grab the remove lock
1391 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1392 if (!NT_SUCCESS(Status
))
1397 Irp
->IoStatus
.Information
= 0;
1398 Irp
->IoStatus
.Status
= Status
;
1399 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1404 // Setup some defaults
1406 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1410 // Check if this is an bus device or the drive
1412 if (DeviceExtension
->Type
== RamdiskBus
)
1415 // Check what the request is
1417 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1420 // Request to create a ramdisk
1422 case FSCTL_CREATE_RAM_DISK
:
1427 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1428 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1434 // We don't handle anything else yet
1443 // Check what the request is
1445 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1447 case IOCTL_DISK_CHECK_VERIFY
:
1448 case IOCTL_STORAGE_CHECK_VERIFY
:
1449 case IOCTL_STORAGE_CHECK_VERIFY2
:
1450 case IOCTL_CDROM_CHECK_VERIFY
:
1456 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1457 case IOCTL_DISK_GET_MEDIA_TYPES
:
1458 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1459 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1462 // Validate the length
1464 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1465 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1470 Status
= STATUS_BUFFER_TOO_SMALL
;
1477 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1478 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1479 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1480 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1481 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1482 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1483 FixedMedia
: RemovableMedia
;
1488 Status
= STATUS_SUCCESS
;
1489 Information
= sizeof(DISK_GEOMETRY
);
1493 // Hack to support ReactOS's broken CDFS
1495 case IOCTL_CDROM_GET_LAST_SESSION
:
1498 // Validate the length
1500 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1501 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1506 Status
= STATUS_BUFFER_TOO_SMALL
;
1513 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1515 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1516 Toc
->FirstTrack
= 1;
1518 Toc
->TrackData
[0].Adr
= 1;
1519 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1520 Toc
->TrackData
[0].TrackNumber
= 1;
1521 Toc
->TrackData
[0].Address
[0] =
1522 Toc
->TrackData
[0].Address
[1] =
1523 Toc
->TrackData
[0].Address
[2] =
1524 Toc
->TrackData
[0].Address
[3] = 0;
1529 Status
= STATUS_SUCCESS
;
1530 Information
= RAMDISK_SESSION_SIZE
;
1533 case IOCTL_CDROM_READ_TOC
:
1536 // Validate the length
1538 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1539 OutputBufferLength
< sizeof(CDROM_TOC
))
1544 Status
= STATUS_BUFFER_TOO_SMALL
;
1551 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1552 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1558 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1559 Toc
->FirstTrack
= 1;
1561 Toc
->TrackData
[0].Adr
= 1;
1562 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1563 Toc
->TrackData
[0].TrackNumber
= 1;
1568 Status
= STATUS_SUCCESS
;
1569 Information
= RAMDISK_TOC_SIZE
;
1572 case IOCTL_DISK_SET_PARTITION_INFO
:
1578 case IOCTL_DISK_GET_PARTITION_INFO
:
1581 // Validate the length
1583 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1584 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1589 Status
= STATUS_BUFFER_TOO_SMALL
;
1594 // Check if we need to do this sync or async
1596 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1599 // Call the helper function
1601 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1606 // Do it asynchronously later
1614 Information
= Irp
->IoStatus
.Information
;
1617 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1623 case IOCTL_DISK_GET_LENGTH_INFO
:
1629 case IOCTL_DISK_IS_WRITABLE
:
1635 case IOCTL_SCSI_MINIPORT
:
1641 case IOCTL_STORAGE_QUERY_PROPERTY
:
1647 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1653 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1659 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1665 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1671 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1677 case IOCTL_VOLUME_OFFLINE
:
1686 // Drive code not emulated
1688 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1693 // If requests drop down here, we just return them complete them
1695 goto CompleteRequest
;
1699 // Queue the request to our worker thread
1702 Status
= SendIrpToThread(DeviceObject
, Irp
);
1708 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1709 if (Status
!= STATUS_PENDING
)
1712 // Complete the request
1714 Irp
->IoStatus
.Status
= Status
;
1715 Irp
->IoStatus
.Information
= Information
;
1716 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1727 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1728 IN PDEVICE_OBJECT DeviceObject
,
1731 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1732 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1733 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1734 ULONG Count
, DiskCount
, FinalCount
;
1735 PLIST_ENTRY ListHead
, NextEntry
;
1736 PDEVICE_OBJECT
* DriveDeviceObject
;
1737 RAMDISK_DEVICE_STATE State
;
1740 // Get the device extension and check if this is a drive
1742 DeviceExtension
= DeviceObject
->DeviceExtension
;
1743 if (DeviceExtension
->Type
== RamdiskDrive
)
1753 // Anything but bus relations, we don't handle
1755 if (Type
) goto PassToNext
;
1758 // Acquire the disk list lock
1760 KeEnterCriticalRegion();
1761 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1764 // Did a device already fill relations?
1766 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1767 if (DeviceRelations
)
1772 Count
= DeviceRelations
->Count
;
1783 // Now loop our drives
1786 ListHead
= &DeviceExtension
->DiskList
;
1787 NextEntry
= ListHead
->Flink
;
1788 while (NextEntry
!= ListHead
)
1791 // As long as it wasn't removed, count it in
1793 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1794 RAMDISK_DRIVE_EXTENSION
,
1796 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1799 // Move to the next one
1801 NextEntry
= NextEntry
->Flink
;
1805 // Now we know our final count
1807 FinalCount
= Count
+ DiskCount
;
1810 // Allocate the structure
1812 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1813 FIELD_OFFSET(DEVICE_RELATIONS
,
1816 sizeof(PDEVICE_OBJECT
),
1818 if (!OurDeviceRelations
)
1823 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1824 KeLeaveCriticalRegion();
1825 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1826 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1827 return STATUS_INSUFFICIENT_RESOURCES
;
1831 // Check if we already had some relations
1838 RtlCopyMemory(OurDeviceRelations
->Objects
,
1839 DeviceRelations
->Objects
,
1840 Count
* sizeof(PDEVICE_OBJECT
));
1846 OurDeviceRelations
->Count
= FinalCount
;
1849 // Now loop our drives again
1851 ListHead
= &DeviceExtension
->DiskList
;
1852 NextEntry
= ListHead
->Flink
;
1853 while (NextEntry
!= ListHead
)
1856 // Go to the end of the list
1858 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1861 // Get the drive state
1863 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1864 RAMDISK_DRIVE_EXTENSION
,
1866 State
= DriveExtension
->State
;
1869 // If it was removed or enumerated, we don't touch the device object
1871 if (State
>= RamdiskStateBusRemoved
)
1874 // If it was removed, we still have to keep track of this though
1876 if (State
== RamdiskStateBusRemoved
)
1879 // Mark it as enumerated now, but don't actually reference it
1881 DriveExtension
->State
= RamdiskStateEnumerated
;
1887 // First time it's enumerated, reference the device object
1889 ObReferenceObject(DriveExtension
->DeviceObject
);
1892 // Save the object pointer, and move on
1894 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1897 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1900 // Move to the next one
1902 NextEntry
= NextEntry
->Flink
;
1908 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1909 KeLeaveCriticalRegion();
1912 // Cleanup old relations
1914 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1919 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1920 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1923 // Pass to the next driver
1926 IoCopyCurrentIrpStackLocationToNext(Irp
);
1927 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1932 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1935 PIO_STACK_LOCATION IoStackLocation
;
1936 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1941 // Get the device extension and stack location
1943 DeviceExtension
= DeviceObject
->DeviceExtension
;
1944 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1945 Minor
= IoStackLocation
->MinorFunction
;
1948 // Check if the bus is removed
1950 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1953 // Only remove-device and query-id are allowed
1955 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
1958 // Fail anything else
1960 Status
= STATUS_NO_SUCH_DEVICE
;
1961 Irp
->IoStatus
.Status
= Status
;
1962 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1968 // Acquire the remove lock
1970 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1971 if (!NT_SUCCESS(Status
))
1976 Irp
->IoStatus
.Information
= 0;
1977 Irp
->IoStatus
.Status
= Status
;
1978 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1983 // Query the IRP type
1987 case IRP_MN_START_DEVICE
:
1989 DPRINT1("PnP IRP: %lx\n", Minor
);
1993 case IRP_MN_QUERY_STOP_DEVICE
:
1995 DPRINT1("PnP IRP: %lx\n", Minor
);
1999 case IRP_MN_CANCEL_STOP_DEVICE
:
2001 DPRINT1("PnP IRP: %lx\n", Minor
);
2005 case IRP_MN_STOP_DEVICE
:
2007 DPRINT1("PnP IRP: %lx\n", Minor
);
2011 case IRP_MN_QUERY_REMOVE_DEVICE
:
2013 DPRINT1("PnP IRP: %lx\n", Minor
);
2017 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2019 DPRINT1("PnP IRP: %lx\n", Minor
);
2023 case IRP_MN_REMOVE_DEVICE
:
2025 DPRINT1("PnP IRP: %lx\n", Minor
);
2029 case IRP_MN_SURPRISE_REMOVAL
:
2031 DPRINT1("PnP IRP: %lx\n", Minor
);
2035 case IRP_MN_QUERY_ID
:
2040 if (DeviceExtension
->Type
== RamdiskDrive
)
2042 DPRINT1("PnP IRP: %lx\n", Minor
);
2047 case IRP_MN_QUERY_BUS_INFORMATION
:
2052 if (DeviceExtension
->Type
== RamdiskDrive
)
2054 DPRINT1("PnP IRP: %lx\n", Minor
);
2061 DPRINT1("PnP IRP: %lx\n", Minor
);
2065 case IRP_MN_QUERY_DEVICE_TEXT
:
2070 if (DeviceExtension
->Type
== RamdiskDrive
)
2072 DPRINT1("PnP IRP: %lx\n", Minor
);
2077 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2080 // Call our main routine
2082 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2084 QueryDeviceRelations
.Type
,
2087 goto ReleaseAndReturn
;
2089 case IRP_MN_QUERY_CAPABILITIES
:
2094 if (DeviceExtension
->Type
== RamdiskDrive
)
2096 DPRINT1("PnP IRP: %lx\n", Minor
);
2101 case IRP_MN_QUERY_RESOURCES
:
2102 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2105 // Complete immediately without touching it
2107 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2108 goto ReleaseAndReturn
;
2112 DPRINT1("Illegal IRP: %lx\n", Minor
);
2119 if (DeviceExtension
->Type
== RamdiskBus
)
2122 // Do we have an attached device?
2124 if (DeviceExtension
->AttachedDevice
)
2129 IoSkipCurrentIrpStackLocation(Irp
);
2130 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2135 // Release the lock and return status
2138 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2144 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2149 return STATUS_SUCCESS
;
2154 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2159 return STATUS_SUCCESS
;
2164 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2169 return STATUS_SUCCESS
;
2174 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2179 return STATUS_SUCCESS
;
2184 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2192 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2193 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2195 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2196 PDEVICE_OBJECT AttachedDevice
;
2198 UNICODE_STRING DeviceName
;
2199 PDEVICE_OBJECT DeviceObject
;
2202 // Only create the bus FDO once
2204 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2207 // Create the bus FDO
2209 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2210 Status
= IoCreateDevice(DriverObject
,
2211 sizeof(RAMDISK_BUS_EXTENSION
),
2213 FILE_DEVICE_BUS_EXTENDER
,
2214 FILE_DEVICE_SECURE_OPEN
,
2217 if (NT_SUCCESS(Status
))
2220 // Initialize the bus FDO extension
2222 DeviceExtension
= DeviceObject
->DeviceExtension
;
2223 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2224 sizeof(RAMDISK_BUS_EXTENSION
));
2227 // Set bus FDO flags
2229 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2232 // Setup the bus FDO extension
2234 DeviceExtension
->Type
= RamdiskBus
;
2235 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2236 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2240 InitializeListHead(&DeviceExtension
->DiskList
);
2241 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2242 DeviceExtension
->DeviceObject
= DeviceObject
;
2245 // Register the RAM disk device interface
2247 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2248 &RamdiskBusInterface
,
2250 &DeviceExtension
->BusDeviceName
);
2251 if (!NT_SUCCESS(Status
))
2256 IoDeleteDevice(DeviceObject
);
2261 // Attach us to the device stack
2263 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2264 PhysicalDeviceObject
);
2265 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2266 if (!AttachedDevice
)
2271 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2272 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2273 IoDeleteDevice(DeviceObject
);
2274 return STATUS_NO_SUCH_DEVICE
;
2278 // Bus FDO is initialized
2280 RamdiskBusFdo
= DeviceObject
;
2283 // Loop for loader block
2288 // Are we being booted from setup? Not yet supported
2290 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2296 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2297 Status
= STATUS_SUCCESS
;
2308 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2309 IN PUNICODE_STRING RegistryPath
)
2311 PCHAR BootDeviceName
, CommandLine
;
2312 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2314 DPRINT("RAM Disk Driver Initialized\n");
2317 // Query ramdisk parameters
2319 QueryParameters(RegistryPath
);
2322 // Save the registry path
2324 DriverRegistryPath
= *RegistryPath
;
2325 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2326 RegistryPath
->Length
+
2329 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2330 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2333 // Set device routines
2335 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2336 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2337 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2338 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2339 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2340 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2341 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2342 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2343 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2344 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2345 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2346 DriverObject
->DriverUnload
= RamdiskUnload
;
2349 // Check for a loader block
2354 // Get the boot device name
2356 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2360 // Check if we're booting from ramdisk
2362 if ((strlen(BootDeviceName
) >= 10) &&
2363 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2366 // We'll have to tell the PnP Manager
2368 ReportDetectedDevice
= TRUE
;
2371 // Check for a command line
2373 CommandLine
= KeLoaderBlock
->LoadOptions
;
2377 // Check if this is an ISO boot
2379 if (strstr(CommandLine
, "RDEXPORTASCD"))
2382 // Remember for later
2384 ExportBootDiskAsCd
= TRUE
;
2388 // Check if this is PE boot
2390 if (strstr(CommandLine
, "MININT"))
2393 // Remember for later
2404 // Installing from Ramdisk isn't supported yet
2406 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2409 // Are we reporting the device
2411 if (ReportDetectedDevice
)
2416 Status
= IoReportDetectedDevice(DriverObject
,
2417 InterfaceTypeUndefined
,
2423 &PhysicalDeviceObject
);
2424 if (NT_SUCCESS(Status
))
2428 // The ReactOS Plug and Play Manager is broken and does not create
2429 // the required keys when reporting a detected device.
2430 // We hack around this ourselves.
2432 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
2433 PhysicalDeviceObject
->DeviceObjectExtension
)
2434 ->DeviceNode
->InstancePath
,
2435 L
"Root\\UNKNOWN\\0000");
2438 // Create the device object
2440 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2441 if (NT_SUCCESS(Status
))
2446 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2447 Status
= STATUS_SUCCESS
;
2456 Status
= STATUS_SUCCESS
;