2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
25 #include <reactos/drivers/ntddrdsk.h>
26 #include "../../../filesystems/fs_rec/fs_rec.h"
31 /* GLOBALS ********************************************************************/
33 #define RAMDISK_SESSION_SIZE \
34 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
36 #define RAMDISK_TOC_SIZE \
37 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
39 #define TOC_DATA_TRACK (0x04)
41 typedef enum _RAMDISK_DEVICE_TYPE
45 } RAMDISK_DEVICE_TYPE
;
47 typedef enum _RAMDISK_DEVICE_STATE
49 RamdiskStateUninitialized
,
54 RamdiskStateBusRemoved
,
55 RamdiskStateEnumerated
,
56 } RAMDISK_DEVICE_STATE
;
58 DEFINE_GUID(RamdiskBusInterface
,
62 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
64 typedef struct _RAMDISK_EXTENSION
66 RAMDISK_DEVICE_TYPE Type
;
67 RAMDISK_DEVICE_STATE State
;
68 PDEVICE_OBJECT DeviceObject
;
69 PDEVICE_OBJECT PhysicalDeviceObject
;
70 PDEVICE_OBJECT AttachedDevice
;
71 IO_REMOVE_LOCK RemoveLock
;
72 UNICODE_STRING DriveDeviceName
;
73 UNICODE_STRING BusDeviceName
;
74 FAST_MUTEX DiskListLock
;
76 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
78 typedef struct _RAMDISK_BUS_EXTENSION
81 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
83 typedef struct _RAMDISK_DRIVE_EXTENSION
86 // Inherited base class
91 // Data we get from the creator
94 UNICODE_STRING GuidString
;
95 UNICODE_STRING SymbolicLinkName
;
97 RAMDISK_CREATE_OPTIONS DiskOptions
;
98 LARGE_INTEGER DiskLength
;
104 // Data we get from the disk
106 ULONG BytesPerSector
;
107 ULONG SectorsPerTrack
;
111 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
113 ULONG MaximumViewLength
;
114 ULONG MaximumPerDiskViewLength
;
115 ULONG ReportDetectedDevice
;
116 ULONG MarkRamdisksAsRemovable
;
117 ULONG MinimumViewCount
;
118 ULONG DefaultViewCount
;
119 ULONG MaximumViewCount
;
120 ULONG MinimumViewLength
;
121 ULONG DefaultViewLength
;
122 UNICODE_STRING DriverRegistryPath
;
123 BOOLEAN ExportBootDiskAsCd
;
125 PDEVICE_OBJECT RamdiskBusFdo
;
127 /* FUNCTIONS ******************************************************************/
131 QueryParameters(IN PUNICODE_STRING RegistryPath
)
133 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
134 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
139 MaximumViewLength
= 0x10000000u
;
140 MaximumPerDiskViewLength
= 0x10000000u
;
141 ReportDetectedDevice
= 0;
142 MarkRamdisksAsRemovable
= 0;
143 MinimumViewCount
= 2;
144 DefaultViewCount
= 16;
145 MaximumViewCount
= 64;
146 MinimumViewLength
= 0x10000u
;
147 DefaultViewLength
= 0x100000u
;
150 // Setup the query table and query the registry
152 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
153 QueryTable
[0].Flags
= 1;
154 QueryTable
[0].Name
= L
"Parameters";
155 QueryTable
[1].Flags
= 32;
156 QueryTable
[1].Name
= L
"ReportDetectedDevice";
157 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
158 QueryTable
[2].Flags
= 32;
159 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
160 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
161 QueryTable
[3].Flags
= 32;
162 QueryTable
[3].Name
= L
"MinimumViewCount";
163 QueryTable
[3].EntryContext
= &MinimumViewCount
;
164 QueryTable
[4].Flags
= 32;
165 QueryTable
[4].Name
= L
"DefaultViewCount";
166 QueryTable
[4].EntryContext
= &DefaultViewCount
;
167 QueryTable
[5].Flags
= 32;
168 QueryTable
[5].Name
= L
"MaximumViewCount";
169 QueryTable
[5].EntryContext
= &MaximumViewCount
;
170 QueryTable
[6].Flags
= 32;
171 QueryTable
[6].Name
= L
"MinimumViewLength";
172 QueryTable
[6].EntryContext
= &MinimumViewLength
;
173 QueryTable
[7].Flags
= 32;
174 QueryTable
[7].Name
= L
"DefaultViewLength";
175 QueryTable
[7].EntryContext
= &DefaultViewLength
;
176 QueryTable
[8].Flags
= 32;
177 QueryTable
[8].Name
= L
"MaximumViewLength";
178 QueryTable
[8].EntryContext
= &MaximumViewLength
;
179 QueryTable
[9].Flags
= 32;
180 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
181 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
182 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
183 RegistryPath
->Buffer
,
189 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
191 MinView
= MinimumViewCount
;
192 if (MinimumViewCount
>= 2)
194 if (MinimumViewCount
> 256) MinView
= 256;
200 MinimumViewCount
= MinView
;
203 // Parse default view count, cannot be bigger than 256 or smaller than minimum
205 DefView
= DefaultViewCount
;
206 if (DefaultViewCount
>= MinView
)
208 if (DefaultViewCount
> 256) DefView
= 256;
214 DefaultViewCount
= DefView
;
217 // Parse maximum view count, cannot be bigger than 256 or smaller than default
219 if (MaximumViewCount
>= DefView
)
221 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
225 MaximumViewCount
= DefView
;
229 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
231 MinViewLength
= MinimumViewLength
;
232 if (MinimumViewLength
>= 0x10000)
234 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
238 MinViewLength
= 0x10000u
;
240 MinimumViewLength
= MinViewLength
;
243 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
245 DefViewLength
= DefaultViewLength
;
246 if (DefaultViewLength
>= MinViewLength
)
248 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
252 DefViewLength
= MinViewLength
;
254 DefaultViewLength
= DefViewLength
;
257 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
259 MaxViewLength
= MaximumViewLength
;
260 if (MaximumViewLength
>= DefViewLength
)
262 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
266 MaxViewLength
= DefViewLength
;
268 MaximumViewLength
= MaxViewLength
;
271 // Parse maximum view length per disk, cannot be smaller than 16MB
273 if (MaximumPerDiskViewLength
>= 0x1000000)
275 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
279 MaximumPerDiskViewLength
= 0x1000000u
;
285 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
286 IN LARGE_INTEGER Offset
,
288 OUT PULONG OutputLength
)
290 PHYSICAL_ADDRESS PhysicalAddress
;
294 LARGE_INTEGER ActualOffset
;
295 LARGE_INTEGER ActualPages
;
298 // We only support boot disks for now
300 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
303 // Calculate the actual offset in the drive
305 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
310 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
313 // Now add the base page
315 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
318 // Calculate final amount of bytes
320 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
323 // Calculate pages spanned for the mapping
325 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
328 // And convert this back to bytes
330 ActualLength
<<= PAGE_SHIFT
;
333 // Get the offset within the page
335 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
338 // Map the I/O Space from the loader
340 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
343 // Return actual offset within the page as well as the length
345 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
346 *OutputLength
= Length
;
352 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
353 IN PVOID BaseAddress
,
354 IN LARGE_INTEGER Offset
,
357 LARGE_INTEGER ActualOffset
;
362 // We only support boot disks for now
364 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
367 // Calculate the actual offset in the drive
369 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
372 // Calculate pages spanned for the mapping
374 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
377 // And convert this back to bytes
379 ActualLength
<<= PAGE_SHIFT
;
382 // Get the offset within the page
384 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
387 // Calculate actual base address where we mapped this
389 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
392 // Unmap the I/O space we got from the loader
394 MmUnmapIoSpace(BaseAddress
, ActualLength
);
399 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
400 IN PRAMDISK_CREATE_INPUT Input
,
401 IN BOOLEAN ValidateOnly
,
402 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
404 ULONG BasePage
, ViewCount
, DiskType
, Length
;
406 PDEVICE_OBJECT DeviceObject
;
407 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
409 WCHAR LocalBuffer
[16];
410 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
411 PPACKED_BOOT_SECTOR BootSector
;
412 BIOS_PARAMETER_BLOCK BiosBlock
;
413 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
415 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
416 ULONG CylinderCount
, SizeByCylinders
;
419 // Check if we're a boot RAM disk
421 DiskType
= Input
->DiskType
;
422 if (DiskType
>= RAMDISK_BOOT_DISK
)
425 // Check if we're an ISO
427 if (DiskType
== RAMDISK_BOOT_DISK
)
430 // NTLDR mounted us somewhere
432 BasePage
= Input
->BasePage
;
433 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
436 // Sanitize disk options
438 Input
->Options
.Fixed
= TRUE
;
439 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
440 Input
->Options
.Readonly
;
441 Input
->Options
.Hidden
= FALSE
;
442 Input
->Options
.NoDosDevice
= FALSE
;
443 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
448 // The only other possibility is a WIM disk
450 if (DiskType
!= RAMDISK_WIM_DISK
)
455 return STATUS_INVALID_PARAMETER
;
459 // Read the view count instead
461 ViewCount
= Input
->ViewCount
;
464 // Sanitize disk options
466 Input
->Options
.Hidden
= FALSE
;
467 Input
->Options
.NoDosDevice
= FALSE
;
468 Input
->Options
.Readonly
= FALSE
;
469 Input
->Options
.NoDriveLetter
= TRUE
;
470 Input
->Options
.Fixed
= TRUE
;
474 // Are we just validating and returning to the user?
476 if (ValidateOnly
) return STATUS_SUCCESS
;
479 // Build the GUID string
481 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
482 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
487 Status
= STATUS_INSUFFICIENT_RESOURCES
;
492 // Allocate our device name
494 Length
= GuidString
.Length
+ 32;
495 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
497 TAG('R', 'a', 'm', 'd'));
503 Status
= STATUS_INSUFFICIENT_RESOURCES
;
508 // Build the device name string
510 DeviceName
.Buffer
= Buffer
;
511 DeviceName
.Length
= Length
- 2;
512 DeviceName
.MaximumLength
= Length
;
513 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
514 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
517 // Create the drive device
519 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
520 sizeof(RAMDISK_DRIVE_EXTENSION
),
522 (Input
->Options
.ExportAsCd
) ?
523 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
527 if (!NT_SUCCESS(Status
)) goto FailCreate
;
530 // Grab the drive extension
532 DriveExtension
= DeviceObject
->DeviceExtension
;
535 // Check if we need a DOS device
537 if (!Input
->Options
.NoDosDevice
)
540 // Build the symbolic link name
542 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
543 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
544 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
545 SymbolicLinkName
.MaximumLength
,
546 TAG('R', 'a', 'm', 'd'));
547 SymbolicLinkName
.Buffer
= Buffer
;
554 L
"\\GLOBAL??\\Ramdisk",
555 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
558 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
559 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
560 if (!NT_SUCCESS(Status
))
565 Input
->Options
.NoDosDevice
= TRUE
;
567 SymbolicLinkName
.Buffer
= NULL
;
575 Input
->Options
.NoDosDevice
= TRUE
;
579 // It this an ISO boot ramdisk?
581 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
584 // Does it need a drive letter?
586 if (!Input
->Options
.NoDriveLetter
)
589 // Build it and take over the existing symbolic link
591 _snwprintf(LocalBuffer
,
593 L
"\\DosDevices\\%wc:",
595 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
596 IoDeleteSymbolicLink(&DriveString
);
597 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
600 // Save the drive letter
602 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
609 // Setup the device object flags
611 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
612 DeviceObject
->AlignmentRequirement
= 1;
615 // Build the drive FDO
617 *NewDriveExtension
= DriveExtension
;
618 DriveExtension
->Type
= RamdiskDrive
;
619 DiskLength
= Input
->DiskLength
;
620 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
621 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
622 TAG('R', 'a', 'm', 'd'),
625 DriveExtension
->DriveDeviceName
= DeviceName
;
626 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
627 DriveExtension
->GuidString
= GuidString
;
628 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
629 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
630 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
631 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
632 DriveExtension
->DiskType
= Input
->DiskType
;
633 DriveExtension
->DiskOptions
= Input
->Options
;
634 DriveExtension
->DiskLength
= DiskLength
;
635 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
636 DriveExtension
->BasePage
= Input
->BasePage
;
637 DriveExtension
->BytesPerSector
= 0;
638 DriveExtension
->SectorsPerTrack
= 0;
639 DriveExtension
->NumberOfHeads
= 0;
642 // Make sure we don't free it later
644 DeviceName
.Buffer
= NULL
;
645 SymbolicLinkName
.Buffer
= NULL
;
646 GuidString
.Buffer
= NULL
;
649 // Check if this is an boot disk, or a registry ram drive
651 if (!(Input
->Options
.ExportAsCd
) &&
652 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
655 // Not an ISO boot, but it's a boot FS -- map it to figure out the
658 CurrentOffset
.QuadPart
= 0;
659 BaseAddress
= RamdiskMapPages(DriveExtension
,
668 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
669 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
670 BytesPerSector
= BiosBlock
.BytesPerSector
;
671 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
672 Heads
= BiosBlock
.Heads
;
677 DriveExtension
->BytesPerSector
= BytesPerSector
;
678 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
679 DriveExtension
->NumberOfHeads
= Heads
;
684 CurrentOffset
.QuadPart
= 0;
685 RamdiskUnmapPages(DriveExtension
,
695 Status
= STATUS_INSUFFICIENT_RESOURCES
;
701 // Check if the drive settings haven't been set yet
703 if ((DriveExtension
->BytesPerSector
== 0) ||
704 (DriveExtension
->SectorsPerTrack
== 0) ||
705 (DriveExtension
->NumberOfHeads
== 0))
708 // Check if this is a CD
710 if (Input
->Options
.ExportAsCd
)
713 // Setup partition parameters default for ISO 9660
715 DriveExtension
->BytesPerSector
= 2048;
716 DriveExtension
->SectorsPerTrack
= 32;
717 DriveExtension
->NumberOfHeads
= 64;
722 // Setup partition parameters default for FAT
724 DriveExtension
->BytesPerSector
= 512;
725 DriveExtension
->SectorsPerTrack
= 128;
726 DriveExtension
->NumberOfHeads
= 16;
731 // Calculate the cylinder size
733 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
734 DriveExtension
->SectorsPerTrack
*
735 DriveExtension
->NumberOfHeads
;
736 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
737 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
738 DriveExtension
->Cylinders
= CylinderCount
;
739 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
742 // Align cylinder size up
744 DriveExtension
->Cylinders
++;
748 // Acquire the disk lock
750 KeEnterCriticalRegion();
751 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
756 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
761 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
762 KeLeaveCriticalRegion();
767 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
768 return STATUS_SUCCESS
;
774 return STATUS_SUCCESS
;
779 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
781 IN BOOLEAN ValidateOnly
)
783 PRAMDISK_CREATE_INPUT Input
;
785 PRAMDISK_BUS_EXTENSION DeviceExtension
;
786 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
788 PWCHAR FileNameStart
, FileNameEnd
;
790 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
793 // Get the device extension and our input data
795 DeviceExtension
= DeviceObject
->DeviceExtension
;
796 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
797 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
800 // Validate input parameters
802 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
803 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
808 return STATUS_INVALID_PARAMETER
;
812 // Validate the disk type
814 DiskType
= Input
->DiskType
;
815 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
818 // Look at the disk type
820 if (DiskType
== RAMDISK_BOOT_DISK
)
823 // We only allow this as an early-init boot
825 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
828 // Save command-line flags
830 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
831 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
835 // Validate the disk type
837 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
840 // If the type isn't CDFS, it has to at least be raw CD
842 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
846 // Check if this is an actual file
848 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
851 // Validate the file name
853 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
854 FileNameEnd
= Input
->FileName
+ 1;
855 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
856 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
860 // Create the actual device
862 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
866 if (NT_SUCCESS(Status
))
869 // Invalidate and set success
871 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
872 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
883 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
886 PRAMDISK_BUS_EXTENSION DeviceExtension
;
888 PIO_STACK_LOCATION IoStackLocation
;
892 // Get the stack location
894 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
897 // Free the work item
899 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
902 // Grab the device extension and lock it
904 DeviceExtension
= DeviceObject
->DeviceExtension
;
905 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
906 if (NT_SUCCESS(Status
))
909 // Discriminate by major code
911 switch (IoStackLocation
->MajorFunction
)
916 case IRP_MJ_DEVICE_CONTROL
:
919 // Let's take a look at the IOCTL
921 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
924 // Ramdisk create request
926 case FSCTL_CREATE_RAM_DISK
:
929 // This time we'll do it for real
931 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
934 case IOCTL_DISK_SET_PARTITION_INFO
:
936 DPRINT1("Set partition info request\n");
941 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
943 DPRINT1("Get drive layout request\n");
948 case IOCTL_DISK_GET_PARTITION_INFO
:
950 DPRINT1("Get partitinon info request\n");
957 DPRINT1("Invalid request\n");
969 // Read or write request
974 DPRINT1("Read/Write request\n");
980 // Internal request (SCSI?)
982 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
984 DPRINT1("SCSI request\n");
992 case IRP_MJ_FLUSH_BUFFERS
:
994 DPRINT1("Flush request\n");
1004 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1013 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1014 Irp
->IoStatus
.Status
= Status
;
1015 Irp
->IoStatus
.Information
= 0;
1016 return IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1022 Irp
->IoStatus
.Status
= Status
;
1023 Irp
->IoStatus
.Information
= 0;
1024 return IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1029 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1032 PIO_WORKITEM WorkItem
;
1035 // Mark the IRP pending
1037 IoMarkIrpPending(Irp
);
1040 // Allocate a work item
1042 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1048 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1049 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1050 return STATUS_PENDING
;
1057 return STATUS_INSUFFICIENT_RESOURCES
;
1063 RamdiskReadWriteReal(IN PIRP Irp
,
1064 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1067 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1068 PIO_STACK_LOCATION IoStackLocation
;
1069 LARGE_INTEGER CurrentOffset
;
1070 ULONG BytesRead
, BytesLeft
, CopyLength
;
1071 PVOID Source
, Destination
;
1075 // Get the MDL and check if it's mapped
1077 Mdl
= Irp
->MdlAddress
;
1078 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
1081 // Use the mapped address
1083 SystemVa
= Mdl
->MappedSystemVa
;
1090 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1095 NormalPagePriority
);
1099 // Make sure we were able to map it
1101 CurrentBase
= SystemVa
;
1102 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1105 // Initialize default
1107 Irp
->IoStatus
.Information
= 0;
1110 // Get the I/O Stack Location and capture the data
1112 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1113 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1114 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1115 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1125 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1129 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1132 // Update our lengths
1134 Irp
->IoStatus
.Information
+= BytesRead
;
1135 CopyLength
= BytesRead
;
1138 // Check if this was a read or write
1140 Status
= STATUS_SUCCESS
;
1141 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1144 // Set our copy parameters
1146 Destination
= CurrentBase
;
1147 Source
= BaseAddress
;
1150 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1153 // Set our copy parameters
1155 Destination
= BaseAddress
;
1156 Source
= CurrentBase
;
1161 RtlCopyMemory(Destination
, Source
, CopyLength
);
1166 // Prepare us for failure
1168 BytesLeft
= CopyLength
;
1169 Status
= STATUS_INVALID_PARAMETER
;
1175 RamdiskUnmapPages(DeviceExtension
,
1181 // Update offset and bytes left
1183 BytesLeft
-= BytesRead
;
1184 CurrentOffset
.QuadPart
+= BytesRead
;
1185 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1188 // Check if we're done
1190 if (!BytesLeft
) return Status
;
1196 RamdiskGetPartitionInfo(IN PIRP Irp
,
1197 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1200 PPARTITION_INFORMATION PartitionInfo
;
1202 LARGE_INTEGER Zero
= {{0}};
1204 PIO_STACK_LOCATION IoStackLocation
;
1207 // Validate the length
1209 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1210 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1211 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1216 Status
= STATUS_BUFFER_TOO_SMALL
;
1217 Irp
->IoStatus
.Status
= Status
;
1218 Irp
->IoStatus
.Information
= 0;
1223 // Map the partition table
1225 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
1231 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1232 Irp
->IoStatus
.Status
= Status
;
1233 Irp
->IoStatus
.Information
= 0;
1238 // Fill out the information
1240 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
1241 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
1242 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
1243 DeviceExtension
->SectorsPerTrack
*
1244 DeviceExtension
->NumberOfHeads
*
1245 DeviceExtension
->Cylinders
;
1246 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
1247 PartitionInfo
->PartitionNumber
= 0;
1248 PartitionInfo
->PartitionType
= PARTITION_FAT32
; //*((PCHAR)BaseAddress + 450);
1249 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
1250 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
1251 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
1253 PartitionInfo
->RewritePartition
= FALSE
;
1256 // Unmap the partition table
1258 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
1263 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1264 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
1265 return STATUS_SUCCESS
;
1270 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1276 Irp
->IoStatus
.Information
= 1;
1277 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1278 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1279 return STATUS_SUCCESS
;
1284 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1287 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1289 LARGE_INTEGER ByteOffset
;
1290 PIO_STACK_LOCATION IoStackLocation
;
1291 NTSTATUS Status
, ReturnStatus
;
1294 // Get the device extension and make sure this isn't a bus
1296 DeviceExtension
= DeviceObject
->DeviceExtension
;
1297 if (DeviceExtension
->Type
== RamdiskBus
)
1302 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1307 // Capture parameters
1309 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1310 Length
= IoStackLocation
->Parameters
.Read
.Length
;
1311 ByteOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1314 // FIXME: Validate offset
1318 // FIXME: Validate sector
1324 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1325 (DeviceExtension
->DiskOptions
.Readonly
))
1328 // Fail, this is read-only
1330 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1335 // See if we want to do this sync or async
1337 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1342 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1347 // Queue it to the worker
1349 Status
= SendIrpToThread(DeviceObject
, Irp
);
1350 ReturnStatus
= STATUS_PENDING
;
1353 // Check if we're pending or not
1355 if (Status
!= STATUS_PENDING
)
1361 Irp
->IoStatus
.Status
= Status
;
1362 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1363 ReturnStatus
= Status
;
1369 return ReturnStatus
;
1374 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1378 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1379 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1380 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1383 PDISK_GEOMETRY DiskGeometry
;
1386 // Grab the remove lock
1388 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1389 if (!NT_SUCCESS(Status
))
1394 Irp
->IoStatus
.Information
= 0;
1395 Irp
->IoStatus
.Status
= Status
;
1396 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1401 // Setup some defaults
1403 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1407 // Check if this is an bus device or the drive
1409 if (DeviceExtension
->Type
== RamdiskBus
)
1412 // Check what the request is
1414 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1417 // Request to create a ramdisk
1419 case FSCTL_CREATE_RAM_DISK
:
1424 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1425 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1431 // We don't handle anything else yet
1440 // Check what the request is
1442 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1444 case IOCTL_DISK_CHECK_VERIFY
:
1445 case IOCTL_STORAGE_CHECK_VERIFY
:
1446 case IOCTL_STORAGE_CHECK_VERIFY2
:
1447 case IOCTL_CDROM_CHECK_VERIFY
:
1453 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1454 case IOCTL_DISK_GET_MEDIA_TYPES
:
1455 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1456 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1459 // Validate the length
1461 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1462 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1467 Status
= STATUS_BUFFER_TOO_SMALL
;
1474 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1475 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1476 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1477 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1478 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1479 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1480 FixedMedia
: RemovableMedia
;
1485 Status
= STATUS_SUCCESS
;
1486 Information
= sizeof(DISK_GEOMETRY
);
1490 // Hack to support ReactOS's broken CDFS
1492 case IOCTL_CDROM_GET_LAST_SESSION
:
1495 // Validate the length
1497 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1498 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1503 Status
= STATUS_BUFFER_TOO_SMALL
;
1510 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1512 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1513 Toc
->FirstTrack
= 1;
1515 Toc
->TrackData
[0].Adr
= 1;
1516 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1517 Toc
->TrackData
[0].TrackNumber
= 1;
1518 Toc
->TrackData
[0].Address
[0] =
1519 Toc
->TrackData
[0].Address
[1] =
1520 Toc
->TrackData
[0].Address
[2] =
1521 Toc
->TrackData
[0].Address
[3] = 0;
1526 Status
= STATUS_SUCCESS
;
1527 Information
= RAMDISK_SESSION_SIZE
;
1530 case IOCTL_CDROM_READ_TOC
:
1533 // Validate the length
1535 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1536 OutputBufferLength
< sizeof(CDROM_TOC
))
1541 Status
= STATUS_BUFFER_TOO_SMALL
;
1548 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1549 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1555 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1556 Toc
->FirstTrack
= 1;
1558 Toc
->TrackData
[0].Adr
= 1;
1559 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1560 Toc
->TrackData
[0].TrackNumber
= 1;
1565 Status
= STATUS_SUCCESS
;
1566 Information
= RAMDISK_TOC_SIZE
;
1569 case IOCTL_DISK_SET_PARTITION_INFO
:
1575 case IOCTL_DISK_GET_PARTITION_INFO
:
1578 // Validate the length
1580 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1581 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1586 Status
= STATUS_BUFFER_TOO_SMALL
;
1591 // Check if we need to do this sync or async
1593 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1596 // Call the helper function
1598 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1603 // Do it asynchronously later
1611 Information
= Irp
->IoStatus
.Information
;
1614 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1620 case IOCTL_DISK_GET_LENGTH_INFO
:
1626 case IOCTL_DISK_IS_WRITABLE
:
1632 case IOCTL_SCSI_MINIPORT
:
1638 case IOCTL_STORAGE_QUERY_PROPERTY
:
1644 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1650 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1656 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1662 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1668 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1674 case IOCTL_VOLUME_OFFLINE
:
1683 // Drive code not emulated
1685 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1690 // If requests drop down here, we just return them complete them
1692 goto CompleteRequest
;
1696 // Queue the request to our worker thread
1699 Status
= SendIrpToThread(DeviceObject
, Irp
);
1705 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1706 if (Status
!= STATUS_PENDING
)
1709 // Complete the request
1711 Irp
->IoStatus
.Status
= Status
;
1712 Irp
->IoStatus
.Information
= Information
;
1713 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1724 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1725 IN PDEVICE_OBJECT DeviceObject
,
1728 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1729 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1730 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1731 ULONG Count
, DiskCount
, FinalCount
;
1732 PLIST_ENTRY ListHead
, NextEntry
;
1733 PDEVICE_OBJECT
* DriveDeviceObject
;
1734 RAMDISK_DEVICE_STATE State
;
1737 // Get the device extension and check if this is a drive
1739 DeviceExtension
= DeviceObject
->DeviceExtension
;
1740 if (DeviceExtension
->Type
== RamdiskDrive
)
1750 // Anything but bus relations, we don't handle
1752 if (Type
) goto PassToNext
;
1755 // Acquire the disk list lock
1757 KeEnterCriticalRegion();
1758 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1761 // Did a device already fill relations?
1763 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1764 if (DeviceRelations
)
1769 Count
= DeviceRelations
->Count
;
1780 // Now loop our drives
1783 ListHead
= &DeviceExtension
->DiskList
;
1784 NextEntry
= ListHead
->Flink
;
1785 while (NextEntry
!= ListHead
)
1788 // As long as it wasn't removed, count it in
1790 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1791 RAMDISK_DRIVE_EXTENSION
,
1793 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1796 // Move to the next one
1798 NextEntry
= NextEntry
->Flink
;
1802 // Now we know our final count
1804 FinalCount
= Count
+ DiskCount
;
1807 // Allocate the structure
1809 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1810 FIELD_OFFSET(DEVICE_RELATIONS
,
1813 sizeof(PDEVICE_OBJECT
),
1814 TAG('R', 'a', 'm', 'd'));
1815 if (!OurDeviceRelations
)
1820 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1821 KeLeaveCriticalRegion();
1822 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1823 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1824 return STATUS_INSUFFICIENT_RESOURCES
;
1828 // Check if we already had some relations
1835 RtlCopyMemory(OurDeviceRelations
->Objects
,
1836 DeviceRelations
->Objects
,
1837 Count
* sizeof(PDEVICE_OBJECT
));
1843 OurDeviceRelations
->Count
= FinalCount
;
1846 // Now loop our drives again
1848 ListHead
= &DeviceExtension
->DiskList
;
1849 NextEntry
= ListHead
->Flink
;
1850 while (NextEntry
!= ListHead
)
1853 // Go to the end of the list
1855 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1858 // Get the drive state
1860 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1861 RAMDISK_DRIVE_EXTENSION
,
1863 State
= DriveExtension
->State
;
1866 // If it was removed or enumerated, we don't touch the device object
1868 if (State
>= RamdiskStateBusRemoved
)
1871 // If it was removed, we still have to keep track of this though
1873 if (State
== RamdiskStateBusRemoved
)
1876 // Mark it as enumerated now, but don't actually reference it
1878 DriveExtension
->State
= RamdiskStateEnumerated
;
1884 // First time it's enumerated, reference the device object
1886 ObReferenceObject(DriveExtension
->DeviceObject
);
1889 // Save the object pointer, and move on
1891 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1894 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1897 // Move to the next one
1899 NextEntry
= NextEntry
->Flink
;
1905 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1906 KeLeaveCriticalRegion();
1909 // Cleanup old relations
1911 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1916 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1917 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1920 // Pass to the next driver
1923 IoCopyCurrentIrpStackLocationToNext(Irp
);
1924 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1929 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1932 PIO_STACK_LOCATION IoStackLocation
;
1933 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1938 // Get the device extension and stack location
1940 DeviceExtension
= DeviceObject
->DeviceExtension
;
1941 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1942 Minor
= IoStackLocation
->MinorFunction
;
1945 // Check if the bus is removed
1947 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1950 // Only remove-device and query-id are allowed
1952 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
1955 // Fail anything else
1957 Status
= STATUS_NO_SUCH_DEVICE
;
1958 Irp
->IoStatus
.Status
= Status
;
1959 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1965 // Acquire the remove lock
1967 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1968 if (!NT_SUCCESS(Status
))
1973 Irp
->IoStatus
.Information
= 0;
1974 Irp
->IoStatus
.Status
= Status
;
1975 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1980 // Query the IRP type
1984 case IRP_MN_START_DEVICE
:
1986 DPRINT1("PnP IRP: %lx\n", Minor
);
1990 case IRP_MN_QUERY_STOP_DEVICE
:
1992 DPRINT1("PnP IRP: %lx\n", Minor
);
1996 case IRP_MN_CANCEL_STOP_DEVICE
:
1998 DPRINT1("PnP IRP: %lx\n", Minor
);
2002 case IRP_MN_STOP_DEVICE
:
2004 DPRINT1("PnP IRP: %lx\n", Minor
);
2008 case IRP_MN_QUERY_REMOVE_DEVICE
:
2010 DPRINT1("PnP IRP: %lx\n", Minor
);
2014 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2016 DPRINT1("PnP IRP: %lx\n", Minor
);
2020 case IRP_MN_REMOVE_DEVICE
:
2022 DPRINT1("PnP IRP: %lx\n", Minor
);
2026 case IRP_MN_SURPRISE_REMOVAL
:
2028 DPRINT1("PnP IRP: %lx\n", Minor
);
2032 case IRP_MN_QUERY_ID
:
2037 if (DeviceExtension
->Type
== RamdiskDrive
)
2039 DPRINT1("PnP IRP: %lx\n", Minor
);
2044 case IRP_MN_QUERY_BUS_INFORMATION
:
2049 if (DeviceExtension
->Type
== RamdiskDrive
)
2051 DPRINT1("PnP IRP: %lx\n", Minor
);
2058 DPRINT1("PnP IRP: %lx\n", Minor
);
2062 case IRP_MN_QUERY_DEVICE_TEXT
:
2067 if (DeviceExtension
->Type
== RamdiskDrive
)
2069 DPRINT1("PnP IRP: %lx\n", Minor
);
2074 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2077 // Call our main routine
2079 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2081 QueryDeviceRelations
.Type
,
2084 goto ReleaseAndReturn
;
2086 case IRP_MN_QUERY_CAPABILITIES
:
2091 if (DeviceExtension
->Type
== RamdiskDrive
)
2093 DPRINT1("PnP IRP: %lx\n", Minor
);
2098 case IRP_MN_QUERY_RESOURCES
:
2099 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2102 // Complete immediately without touching it
2104 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2105 goto ReleaseAndReturn
;
2109 DPRINT1("Illegal IRP: %lx\n", Minor
);
2116 if (DeviceExtension
->Type
== RamdiskBus
)
2119 // Do we have an attached device?
2121 if (DeviceExtension
->AttachedDevice
)
2126 IoSkipCurrentIrpStackLocation(Irp
);
2127 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2132 // Release the lock and return status
2135 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2141 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2146 return STATUS_SUCCESS
;
2151 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2156 return STATUS_SUCCESS
;
2161 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2166 return STATUS_SUCCESS
;
2171 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2176 return STATUS_SUCCESS
;
2181 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2189 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2190 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2192 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2193 PDEVICE_OBJECT AttachedDevice
;
2195 UNICODE_STRING DeviceName
;
2196 PDEVICE_OBJECT DeviceObject
;
2199 // Only create the bus FDO once
2201 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2204 // Create the bus FDO
2206 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2207 Status
= IoCreateDevice(DriverObject
,
2208 sizeof(RAMDISK_BUS_EXTENSION
),
2210 FILE_DEVICE_BUS_EXTENDER
,
2211 FILE_DEVICE_SECURE_OPEN
,
2214 if (NT_SUCCESS(Status
))
2217 // Initialize the bus FDO extension
2219 DeviceExtension
= DeviceObject
->DeviceExtension
;
2220 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2221 sizeof(RAMDISK_BUS_EXTENSION
));
2224 // Set bus FDO flags
2226 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2229 // Setup the bus FDO extension
2231 DeviceExtension
->Type
= RamdiskBus
;
2232 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2233 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2234 TAG('R', 'a', 'm', 'd'),
2237 InitializeListHead(&DeviceExtension
->DiskList
);
2238 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2239 DeviceExtension
->DeviceObject
= DeviceObject
;
2242 // Register the RAM disk device interface
2244 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2245 &RamdiskBusInterface
,
2247 &DeviceExtension
->BusDeviceName
);
2248 if (!NT_SUCCESS(Status
))
2253 IoDeleteDevice(DeviceObject
);
2258 // Attach us to the device stack
2260 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2261 PhysicalDeviceObject
);
2262 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2263 if (!AttachedDevice
)
2268 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2269 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2270 IoDeleteDevice(DeviceObject
);
2271 return STATUS_NO_SUCH_DEVICE
;
2275 // Bus FDO is initialized
2277 RamdiskBusFdo
= DeviceObject
;
2280 // Loop for loader block
2285 // Are we being booted from setup? Not yet supported
2287 ASSERT (!KeLoaderBlock
->SetupLdrBlock
);
2293 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2294 Status
= STATUS_SUCCESS
;
2305 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2306 IN PUNICODE_STRING RegistryPath
)
2308 PCHAR BootDeviceName
, CommandLine
;
2309 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2313 // Query ramdisk parameters
2315 QueryParameters(RegistryPath
);
2318 // Save the registry path
2320 DriverRegistryPath
= *RegistryPath
;
2321 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2322 RegistryPath
->Length
+
2324 TAG('R', 'a', 'm', 'd'));
2325 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2326 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2329 // Set device routines
2331 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2332 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2333 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2334 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2335 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2336 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2337 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2338 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2339 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2340 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2341 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2342 DriverObject
->DriverUnload
= RamdiskUnload
;
2345 // Check for a loader block
2350 // Get the boot device name
2352 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2356 // Check if we're booting from ramdisk
2358 if ((strlen(BootDeviceName
) >= 10) &&
2359 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2362 // We'll have to tell the PnP Manager
2364 ReportDetectedDevice
= TRUE
;
2367 // Check for a command line
2369 CommandLine
= KeLoaderBlock
->LoadOptions
;
2373 // Check if this is an ISO boot
2375 if (strstr(CommandLine
, "RDEXPORTASCD"))
2378 // Remember for later
2380 ExportBootDiskAsCd
= TRUE
;
2384 // Check if this is PE boot
2386 if (strstr(CommandLine
, "MININT"))
2389 // Remember for later
2400 // Installing from Ramdisk isn't supported yet
2402 ASSERT(!KeLoaderBlock
->SetupLdrBlock
);
2405 // Are we reporting the device
2407 if (ReportDetectedDevice
)
2412 Status
= IoReportDetectedDevice(DriverObject
,
2413 InterfaceTypeUndefined
,
2419 &PhysicalDeviceObject
);
2420 if (NT_SUCCESS(Status
))
2424 // The ReactOS Plug and Play Manager is broken and does not create
2425 // the required keys when reporting a detected device.
2426 // We hack around this ourselves.
2428 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
2429 PhysicalDeviceObject
->DeviceObjectExtension
)
2430 ->DeviceNode
->InstancePath
,
2431 L
"Root\\UNKNOWN\\0000");
2434 // Create the device object
2436 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2437 if (NT_SUCCESS(Status
))
2442 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2443 Status
= STATUS_SUCCESS
;
2452 Status
= STATUS_SUCCESS
;