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 *******************************************************************/
24 #include <reactos/drivers/ntddrdsk.h>
25 #include "../../../filesystems/fs_rec/fs_rec.h"
30 /* GLOBALS ********************************************************************/
32 #define RAMDISK_SESSION_SIZE \
33 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
35 #define RAMDISK_TOC_SIZE \
36 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
38 #define TOC_DATA_TRACK (0x04)
40 typedef enum _RAMDISK_DEVICE_TYPE
44 } RAMDISK_DEVICE_TYPE
;
46 typedef enum _RAMDISK_DEVICE_STATE
48 RamdiskStateUninitialized
,
53 RamdiskStateBusRemoved
,
54 RamdiskStateEnumerated
,
55 } RAMDISK_DEVICE_STATE
;
57 DEFINE_GUID(RamdiskBusInterface
,
61 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
63 typedef struct _RAMDISK_EXTENSION
65 RAMDISK_DEVICE_TYPE Type
;
66 RAMDISK_DEVICE_STATE State
;
67 PDEVICE_OBJECT DeviceObject
;
68 PDEVICE_OBJECT PhysicalDeviceObject
;
69 PDEVICE_OBJECT AttachedDevice
;
70 IO_REMOVE_LOCK RemoveLock
;
71 UNICODE_STRING DriveDeviceName
;
72 UNICODE_STRING BusDeviceName
;
73 FAST_MUTEX DiskListLock
;
75 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
77 typedef struct _RAMDISK_BUS_EXTENSION
80 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
82 typedef struct _RAMDISK_DRIVE_EXTENSION
85 // Inherited base class
90 // Data we get from the creator
93 UNICODE_STRING GuidString
;
94 UNICODE_STRING SymbolicLinkName
;
96 RAMDISK_CREATE_OPTIONS DiskOptions
;
97 LARGE_INTEGER DiskLength
;
103 // Data we get from the disk
105 ULONG BytesPerSector
;
106 ULONG SectorsPerTrack
;
110 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
112 ULONG MaximumViewLength
;
113 ULONG MaximumPerDiskViewLength
;
114 ULONG ReportDetectedDevice
;
115 ULONG MarkRamdisksAsRemovable
;
116 ULONG MinimumViewCount
;
117 ULONG DefaultViewCount
;
118 ULONG MaximumViewCount
;
119 ULONG MinimumViewLength
;
120 ULONG DefaultViewLength
;
121 UNICODE_STRING DriverRegistryPath
;
122 BOOLEAN ExportBootDiskAsCd
;
124 PDEVICE_OBJECT RamdiskBusFdo
;
126 /* FUNCTIONS ******************************************************************/
130 QueryParameters(IN PUNICODE_STRING RegistryPath
)
132 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
133 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
138 MaximumViewLength
= 0x10000000u
;
139 MaximumPerDiskViewLength
= 0x10000000u
;
140 ReportDetectedDevice
= 0;
141 MarkRamdisksAsRemovable
= 0;
142 MinimumViewCount
= 2;
143 DefaultViewCount
= 16;
144 MaximumViewCount
= 64;
145 MinimumViewLength
= 0x10000u
;
146 DefaultViewLength
= 0x100000u
;
149 // Setup the query table and query the registry
151 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
152 QueryTable
[0].Flags
= 1;
153 QueryTable
[0].Name
= L
"Parameters";
154 QueryTable
[1].Flags
= 32;
155 QueryTable
[1].Name
= L
"ReportDetectedDevice";
156 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
157 QueryTable
[2].Flags
= 32;
158 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
159 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
160 QueryTable
[3].Flags
= 32;
161 QueryTable
[3].Name
= L
"MinimumViewCount";
162 QueryTable
[3].EntryContext
= &MinimumViewCount
;
163 QueryTable
[4].Flags
= 32;
164 QueryTable
[4].Name
= L
"DefaultViewCount";
165 QueryTable
[4].EntryContext
= &DefaultViewCount
;
166 QueryTable
[5].Flags
= 32;
167 QueryTable
[5].Name
= L
"MaximumViewCount";
168 QueryTable
[5].EntryContext
= &MaximumViewCount
;
169 QueryTable
[6].Flags
= 32;
170 QueryTable
[6].Name
= L
"MinimumViewLength";
171 QueryTable
[6].EntryContext
= &MinimumViewLength
;
172 QueryTable
[7].Flags
= 32;
173 QueryTable
[7].Name
= L
"DefaultViewLength";
174 QueryTable
[7].EntryContext
= &DefaultViewLength
;
175 QueryTable
[8].Flags
= 32;
176 QueryTable
[8].Name
= L
"MaximumViewLength";
177 QueryTable
[8].EntryContext
= &MaximumViewLength
;
178 QueryTable
[9].Flags
= 32;
179 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
180 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
181 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
182 RegistryPath
->Buffer
,
188 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
190 MinView
= MinimumViewCount
;
191 if (MinimumViewCount
>= 2)
193 if (MinimumViewCount
> 256) MinView
= 256;
199 MinimumViewCount
= MinView
;
202 // Parse default view count, cannot be bigger than 256 or smaller than minimum
204 DefView
= DefaultViewCount
;
205 if (DefaultViewCount
>= MinView
)
207 if (DefaultViewCount
> 256) DefView
= 256;
213 DefaultViewCount
= DefView
;
216 // Parse maximum view count, cannot be bigger than 256 or smaller than default
218 if (MaximumViewCount
>= DefView
)
220 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
224 MaximumViewCount
= DefView
;
228 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
230 MinViewLength
= MinimumViewLength
;
231 if (MinimumViewLength
>= 0x10000)
233 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
237 MinViewLength
= 0x10000u
;
239 MinimumViewLength
= MinViewLength
;
242 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
244 DefViewLength
= DefaultViewLength
;
245 if (DefaultViewLength
>= MinViewLength
)
247 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
251 DefViewLength
= MinViewLength
;
253 DefaultViewLength
= DefViewLength
;
256 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
258 MaxViewLength
= MaximumViewLength
;
259 if (MaximumViewLength
>= DefViewLength
)
261 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
265 MaxViewLength
= DefViewLength
;
267 MaximumViewLength
= MaxViewLength
;
270 // Parse maximum view length per disk, cannot be smaller than 16MB
272 if (MaximumPerDiskViewLength
>= 0x1000000)
274 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
278 MaximumPerDiskViewLength
= 0x1000000u
;
284 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
285 IN LARGE_INTEGER Offset
,
287 OUT PULONG OutputLength
)
289 PHYSICAL_ADDRESS PhysicalAddress
;
293 LARGE_INTEGER ActualOffset
;
294 LARGE_INTEGER ActualPages
;
297 // We only support boot disks for now
299 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
302 // Calculate the actual offset in the drive
304 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
309 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
312 // Now add the base page
314 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
317 // Calculate final amount of bytes
319 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
322 // Calculate pages spanned for the mapping
324 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
327 // And convert this back to bytes
329 ActualLength
<<= PAGE_SHIFT
;
332 // Get the offset within the page
334 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
337 // Map the I/O Space from the loader
339 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
342 // Return actual offset within the page as well as the length
344 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
345 *OutputLength
= Length
;
351 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
352 IN PVOID BaseAddress
,
353 IN LARGE_INTEGER Offset
,
356 LARGE_INTEGER ActualOffset
;
361 // We only support boot disks for now
363 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
366 // Calculate the actual offset in the drive
368 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
371 // Calculate pages spanned for the mapping
373 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
376 // And convert this back to bytes
378 ActualLength
<<= PAGE_SHIFT
;
381 // Get the offset within the page
383 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
386 // Calculate actual base address where we mapped this
388 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
391 // Unmap the I/O space we got from the loader
393 MmUnmapIoSpace(BaseAddress
, ActualLength
);
398 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
399 IN PRAMDISK_CREATE_INPUT Input
,
400 IN BOOLEAN ValidateOnly
,
401 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
403 ULONG BasePage
, ViewCount
, DiskType
, Length
;
405 PDEVICE_OBJECT DeviceObject
;
406 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
408 WCHAR LocalBuffer
[16];
409 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
410 PPACKED_BOOT_SECTOR BootSector
;
411 BIOS_PARAMETER_BLOCK BiosBlock
;
412 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
414 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
415 ULONG CylinderCount
, SizeByCylinders
;
418 // Check if we're a boot RAM disk
420 DiskType
= Input
->DiskType
;
421 if (DiskType
>= RAMDISK_BOOT_DISK
)
424 // Check if we're an ISO
426 if (DiskType
== RAMDISK_BOOT_DISK
)
429 // NTLDR mounted us somewhere
431 BasePage
= Input
->BasePage
;
432 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
435 // Sanitize disk options
437 Input
->Options
.Fixed
= TRUE
;
438 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
439 Input
->Options
.Readonly
;
440 Input
->Options
.Hidden
= FALSE
;
441 Input
->Options
.NoDosDevice
= FALSE
;
442 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
447 // The only other possibility is a WIM disk
449 if (DiskType
!= RAMDISK_WIM_DISK
)
454 return STATUS_INVALID_PARAMETER
;
458 // Read the view count instead
460 ViewCount
= Input
->ViewCount
;
463 // Sanitize disk options
465 Input
->Options
.Hidden
= FALSE
;
466 Input
->Options
.NoDosDevice
= FALSE
;
467 Input
->Options
.Readonly
= FALSE
;
468 Input
->Options
.NoDriveLetter
= TRUE
;
469 Input
->Options
.Fixed
= TRUE
;
473 // Are we just validating and returning to the user?
475 if (ValidateOnly
) return STATUS_SUCCESS
;
478 // Build the GUID string
480 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
481 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
486 Status
= STATUS_INSUFFICIENT_RESOURCES
;
491 // Allocate our device name
493 Length
= GuidString
.Length
+ 32;
494 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
502 Status
= STATUS_INSUFFICIENT_RESOURCES
;
507 // Build the device name string
509 DeviceName
.Buffer
= Buffer
;
510 DeviceName
.Length
= Length
- 2;
511 DeviceName
.MaximumLength
= Length
;
512 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
513 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
516 // Create the drive device
518 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
519 sizeof(RAMDISK_DRIVE_EXTENSION
),
521 (Input
->Options
.ExportAsCd
) ?
522 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
526 if (!NT_SUCCESS(Status
)) goto FailCreate
;
529 // Grab the drive extension
531 DriveExtension
= DeviceObject
->DeviceExtension
;
534 // Check if we need a DOS device
536 if (!Input
->Options
.NoDosDevice
)
539 // Build the symbolic link name
541 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
542 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
543 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
544 SymbolicLinkName
.MaximumLength
,
546 SymbolicLinkName
.Buffer
= Buffer
;
553 L
"\\GLOBAL??\\Ramdisk",
554 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
557 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
558 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
559 if (!NT_SUCCESS(Status
))
564 Input
->Options
.NoDosDevice
= TRUE
;
566 SymbolicLinkName
.Buffer
= NULL
;
574 Input
->Options
.NoDosDevice
= TRUE
;
578 // It this an ISO boot ramdisk?
580 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
583 // Does it need a drive letter?
585 if (!Input
->Options
.NoDriveLetter
)
588 // Build it and take over the existing symbolic link
590 _snwprintf(LocalBuffer
,
592 L
"\\DosDevices\\%wc:",
594 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
595 IoDeleteSymbolicLink(&DriveString
);
596 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
599 // Save the drive letter
601 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
608 // Setup the device object flags
610 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
611 DeviceObject
->AlignmentRequirement
= 1;
614 // Build the drive FDO
616 *NewDriveExtension
= DriveExtension
;
617 DriveExtension
->Type
= RamdiskDrive
;
618 DiskLength
= Input
->DiskLength
;
619 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
620 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
624 DriveExtension
->DriveDeviceName
= DeviceName
;
625 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
626 DriveExtension
->GuidString
= GuidString
;
627 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
628 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
629 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
630 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
631 DriveExtension
->DiskType
= Input
->DiskType
;
632 DriveExtension
->DiskOptions
= Input
->Options
;
633 DriveExtension
->DiskLength
= DiskLength
;
634 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
635 DriveExtension
->BasePage
= Input
->BasePage
;
636 DriveExtension
->BytesPerSector
= 0;
637 DriveExtension
->SectorsPerTrack
= 0;
638 DriveExtension
->NumberOfHeads
= 0;
641 // Make sure we don't free it later
643 DeviceName
.Buffer
= NULL
;
644 SymbolicLinkName
.Buffer
= NULL
;
645 GuidString
.Buffer
= NULL
;
648 // Check if this is an boot disk, or a registry ram drive
650 if (!(Input
->Options
.ExportAsCd
) &&
651 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
654 // Not an ISO boot, but it's a boot FS -- map it to figure out the
657 CurrentOffset
.QuadPart
= 0;
658 BaseAddress
= RamdiskMapPages(DriveExtension
,
667 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
668 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
669 BytesPerSector
= BiosBlock
.BytesPerSector
;
670 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
671 Heads
= BiosBlock
.Heads
;
676 DriveExtension
->BytesPerSector
= BytesPerSector
;
677 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
678 DriveExtension
->NumberOfHeads
= Heads
;
683 CurrentOffset
.QuadPart
= 0;
684 RamdiskUnmapPages(DriveExtension
,
694 Status
= STATUS_INSUFFICIENT_RESOURCES
;
700 // Check if the drive settings haven't been set yet
702 if ((DriveExtension
->BytesPerSector
== 0) ||
703 (DriveExtension
->SectorsPerTrack
== 0) ||
704 (DriveExtension
->NumberOfHeads
== 0))
707 // Check if this is a CD
709 if (Input
->Options
.ExportAsCd
)
712 // Setup partition parameters default for ISO 9660
714 DriveExtension
->BytesPerSector
= 2048;
715 DriveExtension
->SectorsPerTrack
= 32;
716 DriveExtension
->NumberOfHeads
= 64;
721 // Setup partition parameters default for FAT
723 DriveExtension
->BytesPerSector
= 512;
724 DriveExtension
->SectorsPerTrack
= 128;
725 DriveExtension
->NumberOfHeads
= 16;
730 // Calculate the cylinder size
732 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
733 DriveExtension
->SectorsPerTrack
*
734 DriveExtension
->NumberOfHeads
;
735 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
736 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
737 DriveExtension
->Cylinders
= CylinderCount
;
738 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
741 // Align cylinder size up
743 DriveExtension
->Cylinders
++;
747 // Acquire the disk lock
749 KeEnterCriticalRegion();
750 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
755 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
760 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
761 KeLeaveCriticalRegion();
766 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
767 return STATUS_SUCCESS
;
773 return STATUS_SUCCESS
;
778 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
780 IN BOOLEAN ValidateOnly
)
782 PRAMDISK_CREATE_INPUT Input
;
784 PRAMDISK_BUS_EXTENSION DeviceExtension
;
785 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
787 PWCHAR FileNameStart
, FileNameEnd
;
789 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
792 // Get the device extension and our input data
794 DeviceExtension
= DeviceObject
->DeviceExtension
;
795 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
796 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
799 // Validate input parameters
801 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
802 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
807 return STATUS_INVALID_PARAMETER
;
811 // Validate the disk type
813 DiskType
= Input
->DiskType
;
814 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
817 // Look at the disk type
819 if (DiskType
== RAMDISK_BOOT_DISK
)
822 // We only allow this as an early-init boot
824 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
827 // Save command-line flags
829 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
830 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
834 // Validate the disk type
836 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
839 // If the type isn't CDFS, it has to at least be raw CD
841 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
845 // Check if this is an actual file
847 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
850 // Validate the file name
852 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
853 FileNameEnd
= Input
->FileName
+ 1;
854 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
855 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
859 // Create the actual device
861 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
865 if (NT_SUCCESS(Status
))
868 // Invalidate and set success
870 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
871 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
882 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
885 PRAMDISK_BUS_EXTENSION DeviceExtension
;
887 PIO_STACK_LOCATION IoStackLocation
;
891 // Get the stack location
893 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
896 // Free the work item
898 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
901 // Grab the device extension and lock it
903 DeviceExtension
= DeviceObject
->DeviceExtension
;
904 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
905 if (NT_SUCCESS(Status
))
908 // Discriminate by major code
910 switch (IoStackLocation
->MajorFunction
)
915 case IRP_MJ_DEVICE_CONTROL
:
918 // Let's take a look at the IOCTL
920 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
923 // Ramdisk create request
925 case FSCTL_CREATE_RAM_DISK
:
928 // This time we'll do it for real
930 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
933 case IOCTL_DISK_SET_PARTITION_INFO
:
935 DPRINT1("Set partition info request\n");
940 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
942 DPRINT1("Get drive layout request\n");
947 case IOCTL_DISK_GET_PARTITION_INFO
:
949 DPRINT1("Get partitinon info request\n");
956 DPRINT1("Invalid request\n");
968 // Read or write request
973 DPRINT1("Read/Write request\n");
979 // Internal request (SCSI?)
981 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
983 DPRINT1("SCSI request\n");
991 case IRP_MJ_FLUSH_BUFFERS
:
993 DPRINT1("Flush request\n");
1003 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1012 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1013 Irp
->IoStatus
.Status
= Status
;
1014 Irp
->IoStatus
.Information
= 0;
1015 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1022 Irp
->IoStatus
.Status
= Status
;
1023 Irp
->IoStatus
.Information
= 0;
1024 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, 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
),
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
,
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
;
2311 DPRINT("RAM Disk Driver Initialized\n");
2314 // Query ramdisk parameters
2316 QueryParameters(RegistryPath
);
2319 // Save the registry path
2321 DriverRegistryPath
= *RegistryPath
;
2322 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2323 RegistryPath
->Length
+
2326 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2327 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2330 // Set device routines
2332 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2333 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2334 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2335 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2336 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2337 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2338 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2339 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2340 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2341 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2342 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2343 DriverObject
->DriverUnload
= RamdiskUnload
;
2346 // Check for a loader block
2351 // Get the boot device name
2353 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2357 // Check if we're booting from ramdisk
2359 if ((strlen(BootDeviceName
) >= 10) &&
2360 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2363 // We'll have to tell the PnP Manager
2365 ReportDetectedDevice
= TRUE
;
2368 // Check for a command line
2370 CommandLine
= KeLoaderBlock
->LoadOptions
;
2374 // Check if this is an ISO boot
2376 if (strstr(CommandLine
, "RDEXPORTASCD"))
2379 // Remember for later
2381 ExportBootDiskAsCd
= TRUE
;
2385 // Check if this is PE boot
2387 if (strstr(CommandLine
, "MININT"))
2390 // Remember for later
2401 // Installing from Ramdisk isn't supported yet
2403 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2406 // Are we reporting the device
2408 if (ReportDetectedDevice
)
2413 Status
= IoReportDetectedDevice(DriverObject
,
2414 InterfaceTypeUndefined
,
2420 &PhysicalDeviceObject
);
2421 if (NT_SUCCESS(Status
))
2425 // The ReactOS Plug and Play Manager is broken and does not create
2426 // the required keys when reporting a detected device.
2427 // We hack around this ourselves.
2429 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
2430 PhysicalDeviceObject
->DeviceObjectExtension
)
2431 ->DeviceNode
->InstancePath
,
2432 L
"Root\\UNKNOWN\\0000");
2435 // Create the device object
2437 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2438 if (NT_SUCCESS(Status
))
2443 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2444 Status
= STATUS_SUCCESS
;
2453 Status
= STATUS_SUCCESS
;