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 DEFINE_GUID(RamdiskDiskInterface
,
70 0x9E, 0xD4, 0x7D, 0x65, 0x47, 0x6C, 0xA7, 0x68);
72 typedef struct _RAMDISK_EXTENSION
74 RAMDISK_DEVICE_TYPE Type
;
75 RAMDISK_DEVICE_STATE State
;
76 PDEVICE_OBJECT DeviceObject
;
77 PDEVICE_OBJECT PhysicalDeviceObject
;
78 PDEVICE_OBJECT AttachedDevice
;
79 IO_REMOVE_LOCK RemoveLock
;
80 UNICODE_STRING DriveDeviceName
;
81 UNICODE_STRING BusDeviceName
;
82 FAST_MUTEX DiskListLock
;
84 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
86 typedef struct _RAMDISK_BUS_EXTENSION
89 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
91 typedef struct _RAMDISK_DRIVE_EXTENSION
94 // Inherited base class
99 // Data we get from the creator
102 UNICODE_STRING GuidString
;
103 UNICODE_STRING SymbolicLinkName
;
105 RAMDISK_CREATE_OPTIONS DiskOptions
;
106 LARGE_INTEGER DiskLength
;
112 // Data we get from the disk
114 ULONG BytesPerSector
;
115 ULONG SectorsPerTrack
;
119 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
121 ULONG MaximumViewLength
;
122 ULONG MaximumPerDiskViewLength
;
123 ULONG ReportDetectedDevice
;
124 ULONG MarkRamdisksAsRemovable
;
125 ULONG MinimumViewCount
;
126 ULONG DefaultViewCount
;
127 ULONG MaximumViewCount
;
128 ULONG MinimumViewLength
;
129 ULONG DefaultViewLength
;
130 UNICODE_STRING DriverRegistryPath
;
131 BOOLEAN ExportBootDiskAsCd
;
133 PDEVICE_OBJECT RamdiskBusFdo
;
135 /* FUNCTIONS ******************************************************************/
139 QueryParameters(IN PUNICODE_STRING RegistryPath
)
141 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
142 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
147 MaximumViewLength
= 0x10000000u
;
148 MaximumPerDiskViewLength
= 0x10000000u
;
149 ReportDetectedDevice
= 0;
150 MarkRamdisksAsRemovable
= 0;
151 MinimumViewCount
= 2;
152 DefaultViewCount
= 16;
153 MaximumViewCount
= 64;
154 MinimumViewLength
= 0x10000u
;
155 DefaultViewLength
= 0x100000u
;
158 // Setup the query table and query the registry
160 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
161 QueryTable
[0].Flags
= 1;
162 QueryTable
[0].Name
= L
"Parameters";
163 QueryTable
[1].Flags
= 32;
164 QueryTable
[1].Name
= L
"ReportDetectedDevice";
165 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
166 QueryTable
[2].Flags
= 32;
167 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
168 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
169 QueryTable
[3].Flags
= 32;
170 QueryTable
[3].Name
= L
"MinimumViewCount";
171 QueryTable
[3].EntryContext
= &MinimumViewCount
;
172 QueryTable
[4].Flags
= 32;
173 QueryTable
[4].Name
= L
"DefaultViewCount";
174 QueryTable
[4].EntryContext
= &DefaultViewCount
;
175 QueryTable
[5].Flags
= 32;
176 QueryTable
[5].Name
= L
"MaximumViewCount";
177 QueryTable
[5].EntryContext
= &MaximumViewCount
;
178 QueryTable
[6].Flags
= 32;
179 QueryTable
[6].Name
= L
"MinimumViewLength";
180 QueryTable
[6].EntryContext
= &MinimumViewLength
;
181 QueryTable
[7].Flags
= 32;
182 QueryTable
[7].Name
= L
"DefaultViewLength";
183 QueryTable
[7].EntryContext
= &DefaultViewLength
;
184 QueryTable
[8].Flags
= 32;
185 QueryTable
[8].Name
= L
"MaximumViewLength";
186 QueryTable
[8].EntryContext
= &MaximumViewLength
;
187 QueryTable
[9].Flags
= 32;
188 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
189 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
190 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
191 RegistryPath
->Buffer
,
197 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
199 MinView
= MinimumViewCount
;
200 if (MinimumViewCount
>= 2)
202 if (MinimumViewCount
> 256) MinView
= 256;
208 MinimumViewCount
= MinView
;
211 // Parse default view count, cannot be bigger than 256 or smaller than minimum
213 DefView
= DefaultViewCount
;
214 if (DefaultViewCount
>= MinView
)
216 if (DefaultViewCount
> 256) DefView
= 256;
222 DefaultViewCount
= DefView
;
225 // Parse maximum view count, cannot be bigger than 256 or smaller than default
227 if (MaximumViewCount
>= DefView
)
229 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
233 MaximumViewCount
= DefView
;
237 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
239 MinViewLength
= MinimumViewLength
;
240 if (MinimumViewLength
>= 0x10000)
242 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
246 MinViewLength
= 0x10000u
;
248 MinimumViewLength
= MinViewLength
;
251 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
253 DefViewLength
= DefaultViewLength
;
254 if (DefaultViewLength
>= MinViewLength
)
256 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
260 DefViewLength
= MinViewLength
;
262 DefaultViewLength
= DefViewLength
;
265 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
267 MaxViewLength
= MaximumViewLength
;
268 if (MaximumViewLength
>= DefViewLength
)
270 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
274 MaxViewLength
= DefViewLength
;
276 MaximumViewLength
= MaxViewLength
;
279 // Parse maximum view length per disk, cannot be smaller than 16MB
281 if (MaximumPerDiskViewLength
>= 0x1000000)
283 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
287 MaximumPerDiskViewLength
= 0x1000000u
;
293 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
294 IN LARGE_INTEGER Offset
,
296 OUT PULONG OutputLength
)
298 PHYSICAL_ADDRESS PhysicalAddress
;
302 LARGE_INTEGER ActualOffset
;
303 LARGE_INTEGER ActualPages
;
306 // We only support boot disks for now
308 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
311 // Calculate the actual offset in the drive
313 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
318 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
321 // Now add the base page
323 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
326 // Calculate final amount of bytes
328 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
331 // Calculate pages spanned for the mapping
333 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
336 // And convert this back to bytes
338 ActualLength
<<= PAGE_SHIFT
;
341 // Get the offset within the page
343 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
346 // Map the I/O Space from the loader
348 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
351 // Return actual offset within the page as well as the length
353 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
354 *OutputLength
= Length
;
360 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
361 IN PVOID BaseAddress
,
362 IN LARGE_INTEGER Offset
,
365 LARGE_INTEGER ActualOffset
;
370 // We only support boot disks for now
372 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
375 // Calculate the actual offset in the drive
377 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
380 // Calculate pages spanned for the mapping
382 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
385 // And convert this back to bytes
387 ActualLength
<<= PAGE_SHIFT
;
390 // Get the offset within the page
392 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
395 // Calculate actual base address where we mapped this
397 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
400 // Unmap the I/O space we got from the loader
402 MmUnmapIoSpace(BaseAddress
, ActualLength
);
407 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
408 IN PRAMDISK_CREATE_INPUT Input
,
409 IN BOOLEAN ValidateOnly
,
410 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
412 ULONG BasePage
, DiskType
, Length
;
415 PDEVICE_OBJECT DeviceObject
;
416 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
418 WCHAR LocalBuffer
[16];
419 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
420 PPACKED_BOOT_SECTOR BootSector
;
421 BIOS_PARAMETER_BLOCK BiosBlock
;
422 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
424 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
425 ULONG CylinderCount
, SizeByCylinders
;
428 // Check if we're a boot RAM disk
430 DiskType
= Input
->DiskType
;
431 if (DiskType
>= RAMDISK_BOOT_DISK
)
434 // Check if we're an ISO
436 if (DiskType
== RAMDISK_BOOT_DISK
)
439 // NTLDR mounted us somewhere
441 BasePage
= Input
->BasePage
;
442 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
445 // Sanitize disk options
447 Input
->Options
.Fixed
= TRUE
;
448 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
449 Input
->Options
.Readonly
;
450 Input
->Options
.Hidden
= FALSE
;
451 Input
->Options
.NoDosDevice
= FALSE
;
452 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
457 // The only other possibility is a WIM disk
459 if (DiskType
!= RAMDISK_WIM_DISK
)
464 return STATUS_INVALID_PARAMETER
;
468 // Read the view count instead
470 //ViewCount = Input->ViewCount;
473 // Sanitize disk options
475 Input
->Options
.Hidden
= FALSE
;
476 Input
->Options
.NoDosDevice
= FALSE
;
477 Input
->Options
.Readonly
= FALSE
;
478 Input
->Options
.NoDriveLetter
= TRUE
;
479 Input
->Options
.Fixed
= TRUE
;
483 // Are we just validating and returning to the user?
485 if (ValidateOnly
) return STATUS_SUCCESS
;
488 // Build the GUID string
490 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
491 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
496 Status
= STATUS_INSUFFICIENT_RESOURCES
;
501 // Allocate our device name
503 Length
= GuidString
.Length
+ 32;
504 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
512 Status
= STATUS_INSUFFICIENT_RESOURCES
;
517 // Build the device name string
519 DeviceName
.Buffer
= Buffer
;
520 DeviceName
.Length
= Length
- 2;
521 DeviceName
.MaximumLength
= Length
;
522 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
523 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
526 // Create the drive device
528 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
529 sizeof(RAMDISK_DRIVE_EXTENSION
),
531 (Input
->Options
.ExportAsCd
) ?
532 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
536 if (!NT_SUCCESS(Status
)) goto FailCreate
;
539 // Grab the drive extension
541 DriveExtension
= DeviceObject
->DeviceExtension
;
544 // Check if we need a DOS device
546 if (!Input
->Options
.NoDosDevice
)
549 // Build the symbolic link name
551 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
552 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
553 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
554 SymbolicLinkName
.MaximumLength
,
556 SymbolicLinkName
.Buffer
= Buffer
;
563 L
"\\GLOBAL??\\Ramdisk",
564 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
567 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
568 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
569 if (!NT_SUCCESS(Status
))
574 Input
->Options
.NoDosDevice
= TRUE
;
576 SymbolicLinkName
.Buffer
= NULL
;
584 Input
->Options
.NoDosDevice
= TRUE
;
588 // It this an ISO boot ramdisk?
590 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
593 // Does it need a drive letter?
595 if (!Input
->Options
.NoDriveLetter
)
598 // Build it and take over the existing symbolic link
600 _snwprintf(LocalBuffer
,
602 L
"\\DosDevices\\%wc:",
604 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
605 IoDeleteSymbolicLink(&DriveString
);
606 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
609 // Save the drive letter
611 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
618 // Setup the device object flags
620 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
621 DeviceObject
->AlignmentRequirement
= 1;
624 // Build the drive FDO
626 *NewDriveExtension
= DriveExtension
;
627 DriveExtension
->Type
= RamdiskDrive
;
628 DiskLength
= Input
->DiskLength
;
629 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
630 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
634 DriveExtension
->DriveDeviceName
= DeviceName
;
635 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
636 DriveExtension
->GuidString
= GuidString
;
637 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
638 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
639 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
640 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
641 DriveExtension
->DiskType
= Input
->DiskType
;
642 DriveExtension
->DiskOptions
= Input
->Options
;
643 DriveExtension
->DiskLength
= DiskLength
;
644 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
645 DriveExtension
->BasePage
= Input
->BasePage
;
646 DriveExtension
->BytesPerSector
= 0;
647 DriveExtension
->SectorsPerTrack
= 0;
648 DriveExtension
->NumberOfHeads
= 0;
651 // Make sure we don't free it later
653 DeviceName
.Buffer
= NULL
;
654 SymbolicLinkName
.Buffer
= NULL
;
655 GuidString
.Buffer
= NULL
;
658 // Check if this is an boot disk, or a registry ram drive
660 if (!(Input
->Options
.ExportAsCd
) &&
661 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
664 // Not an ISO boot, but it's a boot FS -- map it to figure out the
667 CurrentOffset
.QuadPart
= 0;
668 BaseAddress
= RamdiskMapPages(DriveExtension
,
677 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
678 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
679 BytesPerSector
= BiosBlock
.BytesPerSector
;
680 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
681 Heads
= BiosBlock
.Heads
;
686 DriveExtension
->BytesPerSector
= BytesPerSector
;
687 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
688 DriveExtension
->NumberOfHeads
= Heads
;
693 CurrentOffset
.QuadPart
= 0;
694 RamdiskUnmapPages(DriveExtension
,
704 Status
= STATUS_INSUFFICIENT_RESOURCES
;
710 // Check if the drive settings haven't been set yet
712 if ((DriveExtension
->BytesPerSector
== 0) ||
713 (DriveExtension
->SectorsPerTrack
== 0) ||
714 (DriveExtension
->NumberOfHeads
== 0))
717 // Check if this is a CD
719 if (Input
->Options
.ExportAsCd
)
722 // Setup partition parameters default for ISO 9660
724 DriveExtension
->BytesPerSector
= 2048;
725 DriveExtension
->SectorsPerTrack
= 32;
726 DriveExtension
->NumberOfHeads
= 64;
731 // Setup partition parameters default for FAT
733 DriveExtension
->BytesPerSector
= 512;
734 DriveExtension
->SectorsPerTrack
= 128;
735 DriveExtension
->NumberOfHeads
= 16;
740 // Calculate the cylinder size
742 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
743 DriveExtension
->SectorsPerTrack
*
744 DriveExtension
->NumberOfHeads
;
745 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
746 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
747 DriveExtension
->Cylinders
= CylinderCount
;
748 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
751 // Align cylinder size up
753 DriveExtension
->Cylinders
++;
757 // Acquire the disk lock
759 KeEnterCriticalRegion();
760 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
765 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
770 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
771 KeLeaveCriticalRegion();
776 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
777 return STATUS_SUCCESS
;
781 UNIMPLEMENTED_DBGBREAK();
782 return STATUS_SUCCESS
;
787 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
789 IN BOOLEAN ValidateOnly
)
791 PRAMDISK_CREATE_INPUT Input
;
793 PRAMDISK_BUS_EXTENSION DeviceExtension
;
794 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
796 PWCHAR FileNameStart
, FileNameEnd
;
798 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
801 // Get the device extension and our input data
803 DeviceExtension
= DeviceObject
->DeviceExtension
;
804 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
805 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
808 // Validate input parameters
810 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
811 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
816 return STATUS_INVALID_PARAMETER
;
820 // Validate the disk type
822 DiskType
= Input
->DiskType
;
823 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
826 // Look at the disk type
828 if (DiskType
== RAMDISK_BOOT_DISK
)
831 // We only allow this as an early-init boot
833 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
836 // Save command-line flags
838 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
839 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
843 // Validate the disk type
845 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
848 // If the type isn't CDFS, it has to at least be raw CD
850 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
854 // Check if this is an actual file
856 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
859 // Validate the file name
861 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
862 FileNameEnd
= Input
->FileName
+ 1;
863 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
864 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
868 // Create the actual device
870 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
874 if (NT_SUCCESS(Status
))
877 // Invalidate and set success
879 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
880 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
891 RamdiskGetPartitionInfo(IN PIRP Irp
,
892 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
895 PPARTITION_INFORMATION PartitionInfo
;
897 LARGE_INTEGER Zero
= {{0, 0}};
899 PIO_STACK_LOCATION IoStackLocation
;
902 // Validate the length
904 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
905 if (IoStackLocation
->Parameters
.DeviceIoControl
.
906 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
911 Status
= STATUS_BUFFER_TOO_SMALL
;
912 Irp
->IoStatus
.Status
= Status
;
913 Irp
->IoStatus
.Information
= 0;
918 // Map the partition table
920 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
926 Status
= STATUS_INSUFFICIENT_RESOURCES
;
927 Irp
->IoStatus
.Status
= Status
;
928 Irp
->IoStatus
.Information
= 0;
933 // Fill out the information
935 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
936 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
937 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
938 DeviceExtension
->SectorsPerTrack
*
939 DeviceExtension
->NumberOfHeads
*
940 DeviceExtension
->Cylinders
;
941 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
942 PartitionInfo
->PartitionNumber
= 0;
943 PartitionInfo
->PartitionType
= *((PCHAR
)BaseAddress
+ 450);
944 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
945 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
946 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
948 PartitionInfo
->RewritePartition
= FALSE
;
951 // Unmap the partition table
953 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
958 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
959 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
960 return STATUS_SUCCESS
;
965 RamdiskSetPartitionInfo(IN PIRP Irp
,
966 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
971 PIO_STACK_LOCATION Stack
;
972 LARGE_INTEGER Zero
= {{0, 0}};
973 PPARTITION_INFORMATION PartitionInfo
;
976 // First validate input
978 Stack
= IoGetCurrentIrpStackLocation(Irp
);
979 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(PARTITION_INFORMATION
))
981 Status
= STATUS_INVALID_PARAMETER
;
988 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &BytesRead
);
989 if (BaseAddress
== NULL
)
991 Status
= STATUS_INSUFFICIENT_RESOURCES
;
996 // Set the new partition type
997 // On partition 0, field system indicator
999 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
1000 *((PCHAR
)BaseAddress
+ 450) = PartitionInfo
->PartitionType
;
1005 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, BytesRead
);
1006 Status
= STATUS_SUCCESS
;
1009 Irp
->IoStatus
.Status
= Status
;
1010 Irp
->IoStatus
.Information
= 0;
1016 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
1019 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1021 PIO_STACK_LOCATION IoStackLocation
;
1025 // Get the stack location
1027 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1030 // Free the work item
1032 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
1035 // Grab the device extension and lock it
1037 DeviceExtension
= DeviceObject
->DeviceExtension
;
1038 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1039 if (NT_SUCCESS(Status
))
1042 // Discriminate by major code
1044 switch (IoStackLocation
->MajorFunction
)
1049 case IRP_MJ_DEVICE_CONTROL
:
1052 // Let's take a look at the IOCTL
1054 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1057 // Ramdisk create request
1059 case FSCTL_CREATE_RAM_DISK
:
1062 // This time we'll do it for real
1064 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
1067 case IOCTL_DISK_SET_PARTITION_INFO
:
1069 Status
= RamdiskSetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
1072 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1074 UNIMPLEMENTED_DBGBREAK("Get drive layout request\n");
1077 case IOCTL_DISK_GET_PARTITION_INFO
:
1079 Status
= RamdiskGetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
1084 UNIMPLEMENTED_DBGBREAK("Invalid request\n");
1094 // Read or write request
1099 UNIMPLEMENTED_DBGBREAK("Read/Write request\n");
1103 // Internal request (SCSI?)
1105 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
1107 UNIMPLEMENTED_DBGBREAK("SCSI request\n");
1113 case IRP_MJ_FLUSH_BUFFERS
:
1115 UNIMPLEMENTED_DBGBREAK("Flush request\n");
1123 UNIMPLEMENTED_DBGBREAK("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1130 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1131 Irp
->IoStatus
.Status
= Status
;
1132 Irp
->IoStatus
.Information
= 0;
1133 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1140 Irp
->IoStatus
.Status
= Status
;
1141 Irp
->IoStatus
.Information
= 0;
1142 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1147 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1150 PIO_WORKITEM WorkItem
;
1153 // Mark the IRP pending
1155 IoMarkIrpPending(Irp
);
1158 // Allocate a work item
1160 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1166 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1167 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1168 return STATUS_PENDING
;
1175 return STATUS_INSUFFICIENT_RESOURCES
;
1181 RamdiskReadWriteReal(IN PIRP Irp
,
1182 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1185 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1186 PIO_STACK_LOCATION IoStackLocation
;
1187 LARGE_INTEGER CurrentOffset
;
1188 ULONG BytesRead
, BytesLeft
, CopyLength
;
1189 PVOID Source
, Destination
;
1193 // Get the MDL and check if it's mapped
1195 Mdl
= Irp
->MdlAddress
;
1196 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
1199 // Use the mapped address
1201 SystemVa
= Mdl
->MappedSystemVa
;
1208 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1213 NormalPagePriority
);
1217 // Make sure we were able to map it
1219 CurrentBase
= SystemVa
;
1220 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1223 // Initialize default
1225 Irp
->IoStatus
.Information
= 0;
1228 // Get the I/O Stack Location and capture the data
1230 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1231 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1232 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1233 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1243 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1247 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1250 // Update our lengths
1252 Irp
->IoStatus
.Information
+= BytesRead
;
1253 CopyLength
= BytesRead
;
1256 // Check if this was a read or write
1258 Status
= STATUS_SUCCESS
;
1259 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1262 // Set our copy parameters
1264 Destination
= CurrentBase
;
1265 Source
= BaseAddress
;
1268 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1271 // Set our copy parameters
1273 Destination
= BaseAddress
;
1274 Source
= CurrentBase
;
1279 RtlCopyMemory(Destination
, Source
, CopyLength
);
1284 // Prepare us for failure
1286 BytesLeft
= CopyLength
;
1287 Status
= STATUS_INVALID_PARAMETER
;
1293 RamdiskUnmapPages(DeviceExtension
,
1299 // Update offset and bytes left
1301 BytesLeft
-= BytesRead
;
1302 CurrentOffset
.QuadPart
+= BytesRead
;
1303 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1306 // Check if we're done
1308 if (!BytesLeft
) return Status
;
1314 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1320 Irp
->IoStatus
.Information
= 1;
1321 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1322 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1323 return STATUS_SUCCESS
;
1328 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1331 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1333 //LARGE_INTEGER ByteOffset;
1334 PIO_STACK_LOCATION IoStackLocation
;
1335 NTSTATUS Status
, ReturnStatus
;
1338 // Get the device extension and make sure this isn't a bus
1340 DeviceExtension
= DeviceObject
->DeviceExtension
;
1341 if (DeviceExtension
->Type
== RamdiskBus
)
1346 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1351 // Capture parameters
1353 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1354 //Length = IoStackLocation->Parameters.Read.Length;
1355 //ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
1358 // FIXME: Validate offset
1362 // FIXME: Validate sector
1368 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1369 (DeviceExtension
->DiskOptions
.Readonly
))
1372 // Fail, this is read-only
1374 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1379 // See if we want to do this sync or async
1381 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1386 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1391 // Queue it to the worker
1393 Status
= SendIrpToThread(DeviceObject
, Irp
);
1394 ReturnStatus
= STATUS_PENDING
;
1397 // Check if we're pending or not
1399 if (Status
!= STATUS_PENDING
)
1405 Irp
->IoStatus
.Status
= Status
;
1406 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1407 ReturnStatus
= Status
;
1413 return ReturnStatus
;
1418 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1422 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1423 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1424 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1427 PDISK_GEOMETRY DiskGeometry
;
1430 // Grab the remove lock
1432 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1433 if (!NT_SUCCESS(Status
))
1438 Irp
->IoStatus
.Information
= 0;
1439 Irp
->IoStatus
.Status
= Status
;
1440 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1445 // Setup some defaults
1447 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1451 // Check if this is an bus device or the drive
1453 if (DeviceExtension
->Type
== RamdiskBus
)
1456 // Check what the request is
1458 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1461 // Request to create a ramdisk
1463 case FSCTL_CREATE_RAM_DISK
:
1468 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1469 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1475 // We don't handle anything else yet
1477 UNIMPLEMENTED_DBGBREAK();
1483 // Check what the request is
1485 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1487 case IOCTL_DISK_CHECK_VERIFY
:
1488 case IOCTL_STORAGE_CHECK_VERIFY
:
1489 case IOCTL_STORAGE_CHECK_VERIFY2
:
1490 case IOCTL_CDROM_CHECK_VERIFY
:
1493 // Just pretend it's OK, don't do more
1495 Status
= STATUS_SUCCESS
;
1498 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1499 case IOCTL_DISK_GET_MEDIA_TYPES
:
1500 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1501 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1504 // Validate the length
1506 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1507 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1512 Status
= STATUS_BUFFER_TOO_SMALL
;
1519 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1520 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1521 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1522 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1523 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1524 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1525 FixedMedia
: RemovableMedia
;
1530 Status
= STATUS_SUCCESS
;
1531 Information
= sizeof(DISK_GEOMETRY
);
1534 case IOCTL_CDROM_READ_TOC
:
1537 // Validate the length
1539 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1540 OutputBufferLength
< sizeof(CDROM_TOC
))
1545 Status
= STATUS_BUFFER_TOO_SMALL
;
1552 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1553 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1559 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1560 Toc
->FirstTrack
= 1;
1562 Toc
->TrackData
[0].Adr
= 1;
1563 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1564 Toc
->TrackData
[0].TrackNumber
= 1;
1569 Status
= STATUS_SUCCESS
;
1570 Information
= RAMDISK_TOC_SIZE
;
1573 case IOCTL_DISK_SET_PARTITION_INFO
:
1575 Status
= RamdiskSetPartitionInfo(Irp
, DriveExtension
);
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
:
1619 UNIMPLEMENTED_DBGBREAK();
1622 case IOCTL_DISK_GET_LENGTH_INFO
:
1624 UNIMPLEMENTED_DBGBREAK();
1627 case IOCTL_DISK_IS_WRITABLE
:
1629 UNIMPLEMENTED_DBGBREAK();
1632 case IOCTL_SCSI_MINIPORT
:
1634 UNIMPLEMENTED_DBGBREAK();
1637 case IOCTL_STORAGE_QUERY_PROPERTY
:
1639 UNIMPLEMENTED_DBGBREAK();
1642 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1644 UNIMPLEMENTED_DBGBREAK();
1647 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1649 UNIMPLEMENTED_DBGBREAK();
1652 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1654 UNIMPLEMENTED_DBGBREAK();
1657 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1659 UNIMPLEMENTED_DBGBREAK();
1662 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1664 UNIMPLEMENTED_DBGBREAK();
1667 case IOCTL_VOLUME_OFFLINE
:
1669 UNIMPLEMENTED_DBGBREAK();
1675 // Drive code not emulated
1677 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1682 // If requests drop down here, we just return them complete them
1684 goto CompleteRequest
;
1688 // Queue the request to our worker thread
1691 Status
= SendIrpToThread(DeviceObject
, Irp
);
1697 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1698 if (Status
!= STATUS_PENDING
)
1701 // Complete the request
1703 Irp
->IoStatus
.Status
= Status
;
1704 Irp
->IoStatus
.Information
= Information
;
1705 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1716 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1717 IN PDEVICE_OBJECT DeviceObject
,
1720 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1721 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1722 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1723 ULONG Count
, DiskCount
, FinalCount
;
1724 PLIST_ENTRY ListHead
, NextEntry
;
1725 PDEVICE_OBJECT
* DriveDeviceObject
;
1726 RAMDISK_DEVICE_STATE State
;
1729 // Get the device extension and check if this is a drive
1731 DeviceExtension
= DeviceObject
->DeviceExtension
;
1732 if (DeviceExtension
->Type
== RamdiskDrive
)
1737 UNIMPLEMENTED_DBGBREAK();
1741 // Anything but bus relations, we don't handle
1743 if (Type
!= BusRelations
) goto PassToNext
;
1746 // Acquire the disk list lock
1748 KeEnterCriticalRegion();
1749 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1752 // Did a device already fill relations?
1754 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1755 if (DeviceRelations
)
1760 Count
= DeviceRelations
->Count
;
1771 // Now loop our drives
1774 ListHead
= &DeviceExtension
->DiskList
;
1775 NextEntry
= ListHead
->Flink
;
1776 while (NextEntry
!= ListHead
)
1779 // As long as it wasn't removed, count it in
1781 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1782 RAMDISK_DRIVE_EXTENSION
,
1784 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1787 // Move to the next one
1789 NextEntry
= NextEntry
->Flink
;
1793 // Now we know our final count
1795 FinalCount
= Count
+ DiskCount
;
1798 // Allocate the structure
1800 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1801 FIELD_OFFSET(DEVICE_RELATIONS
,
1804 sizeof(PDEVICE_OBJECT
),
1806 if (!OurDeviceRelations
)
1811 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1812 KeLeaveCriticalRegion();
1813 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1814 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1815 return STATUS_INSUFFICIENT_RESOURCES
;
1819 // Check if we already had some relations
1826 RtlCopyMemory(OurDeviceRelations
->Objects
,
1827 DeviceRelations
->Objects
,
1828 Count
* sizeof(PDEVICE_OBJECT
));
1834 OurDeviceRelations
->Count
= FinalCount
;
1837 // Now loop our drives again
1839 ListHead
= &DeviceExtension
->DiskList
;
1840 NextEntry
= ListHead
->Flink
;
1841 while (NextEntry
!= ListHead
)
1844 // Go to the end of the list
1846 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1849 // Get the drive state
1851 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1852 RAMDISK_DRIVE_EXTENSION
,
1854 State
= DriveExtension
->State
;
1857 // If it was removed or enumerated, we don't touch the device object
1859 if (State
>= RamdiskStateBusRemoved
)
1862 // If it was removed, we still have to keep track of this though
1864 if (State
== RamdiskStateBusRemoved
)
1867 // Mark it as enumerated now, but don't actually reference it
1869 DriveExtension
->State
= RamdiskStateEnumerated
;
1875 // First time it's enumerated, reference the device object
1877 ObReferenceObject(DriveExtension
->DeviceObject
);
1880 // Save the object pointer, and move on
1882 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1885 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1888 // Move to the next one
1890 NextEntry
= NextEntry
->Flink
;
1896 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1897 KeLeaveCriticalRegion();
1900 // Cleanup old relations
1902 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1907 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1908 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1911 // Pass to the next driver
1914 IoCopyCurrentIrpStackLocationToNext(Irp
);
1915 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1920 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject
,
1923 UNIMPLEMENTED_DBGBREAK();
1924 return STATUS_SUCCESS
;
1929 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject
,
1933 PLIST_ENTRY ListHead
, NextEntry
;
1934 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1935 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1937 DeviceExtension
= DeviceObject
->DeviceExtension
;
1940 // Acquire disks list lock
1942 KeEnterCriticalRegion();
1943 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1948 ListHead
= &DeviceExtension
->DiskList
;
1949 NextEntry
= ListHead
->Flink
;
1950 while (NextEntry
!= ListHead
)
1952 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1953 RAMDISK_DRIVE_EXTENSION
,
1959 IoAcquireRemoveLock(&DriveExtension
->RemoveLock
, NULL
);
1960 RamdiskDeleteDiskDevice(DriveExtension
->PhysicalDeviceObject
, NULL
);
1963 // RamdiskDeleteDiskDevice releases list lock, so reacquire it
1965 KeEnterCriticalRegion();
1966 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1970 // Release disks list lock
1972 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1973 KeLeaveCriticalRegion();
1976 // Prepare to pass to the lower driver
1978 IoSkipCurrentIrpStackLocation(Irp
);
1980 // Here everything went fine
1982 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1985 // Call lower driver
1987 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1992 DeviceExtension
->State
= RamdiskStateBusRemoved
;
1995 // Release the lock, and ensure that everyone
1996 // has finished its job before we continue
1997 // The lock has been acquired by the dispatcher
1999 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, Irp
);
2002 // If there's a drive name
2004 if (DeviceExtension
->DriveDeviceName
.Buffer
)
2007 // Inform it's going to be disabled
2008 // and free the drive name
2010 IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, FALSE
);
2011 RtlFreeUnicodeString(&DeviceExtension
->DriveDeviceName
);
2015 // Part from the stack, detach from lower device
2017 IoDetachDevice(DeviceExtension
->AttachedDevice
);
2020 // Finally, delete device
2022 RamdiskBusFdo
= NULL
;
2023 IoDeleteDevice(DeviceObject
);
2026 // Return status from lower driver
2033 RamdiskQueryId(IN PRAMDISK_DRIVE_EXTENSION DriveExtension
,
2037 PIO_STACK_LOCATION IoStackLocation
;
2038 PWSTR OutputString
= NULL
;
2041 Status
= STATUS_SUCCESS
;
2042 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2045 // Get what is being queried
2047 switch (IoStackLocation
->Parameters
.QueryId
.IdType
)
2049 case BusQueryDeviceID
:
2052 // Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
2053 // In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
2054 // chars to store Ramdisk\RamVolume instead
2056 StringLength
= 4 * (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
) + sizeof(L
"Ramdisk\\RamDisk");
2057 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
2058 if (OutputString
== NULL
)
2060 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2064 wcsncpy(OutputString
, L
"Ramdisk\\", StringLength
/ sizeof(WCHAR
));
2065 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
2067 wcsncat(OutputString
, L
"RamVolume", StringLength
/ sizeof(WCHAR
));
2071 wcsncat(OutputString
, L
"RamDisk", StringLength
/ sizeof(WCHAR
));
2076 case BusQueryHardwareIDs
:
2079 // Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
2080 // In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
2081 // chars to store Ramdisk\RamVolume instead
2082 // We also need an extra char, because it is required that the string
2083 // is null-terminated twice
2085 StringLength
= 4 * (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
) +
2086 sizeof(UNICODE_NULL
) + sizeof(L
"Ramdisk\\RamDisk");
2087 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
2088 if (OutputString
== NULL
)
2090 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2094 wcsncpy(OutputString
, L
"Ramdisk\\", StringLength
/ sizeof(WCHAR
));
2095 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
2097 wcsncat(OutputString
, L
"RamVolume", StringLength
/ sizeof(WCHAR
));
2101 wcsncat(OutputString
, L
"RamDisk", StringLength
/ sizeof(WCHAR
));
2103 OutputString
[(StringLength
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
2107 case BusQueryCompatibleIDs
:
2109 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
2111 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2115 StringLength
= sizeof(L
"GenDisk");
2116 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
2117 if (OutputString
== NULL
)
2119 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2123 wcsncpy(OutputString
, L
"GenDisk", StringLength
/ sizeof(WCHAR
));
2124 OutputString
[(StringLength
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
2128 case BusQueryInstanceID
:
2130 OutputString
= ExAllocatePoolWithTag(PagedPool
, DriveExtension
->GuidString
.MaximumLength
, 'dmaR');
2131 if (OutputString
== NULL
)
2133 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2137 wcsncpy(OutputString
, DriveExtension
->GuidString
.Buffer
, DriveExtension
->GuidString
.MaximumLength
/ sizeof(WCHAR
));
2141 case BusQueryDeviceSerialNumber
:
2150 Irp
->IoStatus
.Status
= Status
;
2151 Irp
->IoStatus
.Information
= (ULONG_PTR
)OutputString
;
2152 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2158 RamdiskQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
2162 PIO_STACK_LOCATION IoStackLocation
;
2163 PDEVICE_CAPABILITIES DeviceCapabilities
;
2164 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
2166 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2167 DeviceCapabilities
= IoStackLocation
->Parameters
.DeviceCapabilities
.Capabilities
;
2168 DriveExtension
= DeviceObject
->DeviceExtension
;
2171 // Validate our input buffer
2173 if (DeviceCapabilities
->Version
!= 1 || DeviceCapabilities
->Size
< sizeof(DEVICE_CAPABILITIES
))
2175 Status
= STATUS_UNSUCCESSFUL
;
2180 // And set everything we know about our capabilities
2182 DeviceCapabilities
->Removable
= MarkRamdisksAsRemovable
;
2183 DeviceCapabilities
->UniqueID
= TRUE
;
2184 DeviceCapabilities
->SilentInstall
= TRUE
;
2185 DeviceCapabilities
->RawDeviceOK
= TRUE
;
2186 DeviceCapabilities
->SurpriseRemovalOK
= (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
);
2187 DeviceCapabilities
->NoDisplayInUI
= TRUE
;
2188 Status
= STATUS_SUCCESS
;
2191 Irp
->IoStatus
.Status
= Status
;
2192 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2198 RamdiskQueryDeviceText(IN PRAMDISK_DRIVE_EXTENSION DriveExtension
,
2202 PIO_STACK_LOCATION IoStackLocation
;
2203 DEVICE_TEXT_TYPE DeviceTextType
;
2204 PWSTR OutputString
= NULL
;
2206 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2207 DeviceTextType
= IoStackLocation
->Parameters
.QueryDeviceText
.DeviceTextType
;
2208 Status
= STATUS_SUCCESS
;
2211 // Just copy our constants, according to the input
2213 switch (DeviceTextType
)
2215 case DeviceTextDescription
:
2217 OutputString
= ExAllocatePoolWithTag(PagedPool
, sizeof(L
"RamDisk"), 'dmaR');
2218 if (OutputString
== NULL
)
2220 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2224 wcsncpy(OutputString
, L
"RamDisk", sizeof(L
"RamDisk") / sizeof(WCHAR
));
2228 case DeviceTextLocationInformation
:
2230 OutputString
= ExAllocatePoolWithTag(PagedPool
, sizeof(L
"RamDisk\\0"), 'dmaR');
2231 if (OutputString
== NULL
)
2233 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2237 wcsncpy(OutputString
, L
"RamDisk\\0", sizeof(L
"RamDisk\\0") / sizeof(WCHAR
));
2242 Irp
->IoStatus
.Status
= Status
;
2243 Irp
->IoStatus
.Information
= (ULONG_PTR
)OutputString
;
2244 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2250 RamdiskQueryBusInformation(IN PDEVICE_OBJECT DeviceObject
,
2253 PPNP_BUS_INFORMATION PnpBusInfo
;
2254 NTSTATUS Status
= STATUS_SUCCESS
;
2257 // Allocate output memory
2259 PnpBusInfo
= ExAllocatePoolWithTag(PagedPool
, sizeof(PNP_BUS_INFORMATION
), 'dmaR');
2260 if (PnpBusInfo
== NULL
)
2262 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2267 // Copy our bus GUID and set our legacy type
2269 RtlCopyMemory(&PnpBusInfo
->BusTypeGuid
, &GUID_BUS_TYPE_RAMDISK
, sizeof(GUID
));
2270 PnpBusInfo
->LegacyBusType
= PNPBus
;
2271 PnpBusInfo
->BusNumber
= 0;
2274 Irp
->IoStatus
.Status
= Status
;
2275 Irp
->IoStatus
.Information
= (ULONG_PTR
)PnpBusInfo
;
2276 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2282 RamdiskIoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
,
2288 // Just set the event to unlock caller
2290 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
2292 return STATUS_MORE_PROCESSING_REQUIRED
;
2297 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
2300 PIO_STACK_LOCATION IoStackLocation
;
2301 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2307 // Get the device extension and stack location
2309 DeviceExtension
= DeviceObject
->DeviceExtension
;
2310 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2311 Minor
= IoStackLocation
->MinorFunction
;
2314 // Check if the bus is removed
2316 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
2319 // Only remove-device and query-id are allowed
2321 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) && (Minor
!= IRP_MN_QUERY_ID
))
2324 // Fail anything else
2326 Status
= STATUS_NO_SUCH_DEVICE
;
2327 Irp
->IoStatus
.Status
= Status
;
2328 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2334 // Acquire the remove lock
2336 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2337 if (!NT_SUCCESS(Status
))
2342 Irp
->IoStatus
.Information
= 0;
2343 Irp
->IoStatus
.Status
= Status
;
2344 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2349 // Query the IRP type
2353 case IRP_MN_START_DEVICE
:
2355 if (DeviceExtension
->Type
== RamdiskDrive
)
2358 DEVICE_INSTALL_STATE InstallState
;
2359 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
;
2362 // If we already have a drive name, free it
2364 if (DriveExtension
->DriveDeviceName
.Buffer
)
2366 ExFreePool(DriveExtension
->DriveDeviceName
.Buffer
);
2370 // Register our device interface
2372 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
2374 Status
= IoRegisterDeviceInterface(DeviceObject
,
2375 &GUID_DEVINTERFACE_VOLUME
,
2377 &DriveExtension
->DriveDeviceName
);
2381 Status
= IoRegisterDeviceInterface(DeviceObject
,
2382 &RamdiskDiskInterface
,
2384 &DriveExtension
->DriveDeviceName
);
2388 // If we were asked not to assign a drive letter or
2389 // if getting a name failed, just return saying
2390 // we're now started
2392 if (DriveExtension
->DiskOptions
.NoDriveLetter
||
2393 DriveExtension
->DriveDeviceName
.Buffer
== NULL
)
2395 DriveExtension
->State
= RamdiskStateStarted
;
2396 Irp
->IoStatus
.Status
= Status
;
2401 // Now get our installation state
2403 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyInstallState
,
2404 sizeof(InstallState
), &InstallState
, &ResultLength
);
2406 // If querying the information failed, assume success
2408 if (!NT_SUCCESS(Status
))
2410 InstallState
= InstallStateInstalled
;
2414 // If we were properly installed, then, enable the interface
2416 if (InstallState
== InstallStateInstalled
)
2418 Status
= IoSetDeviceInterfaceState(&DriveExtension
->DriveDeviceName
, TRUE
);
2424 DriveExtension
->State
= RamdiskStateStarted
;
2425 Irp
->IoStatus
.Status
= Status
;
2430 // Prepare next stack to pass it down
2432 IoCopyCurrentIrpStackLocationToNext(Irp
);
2435 // Initialize our notification event & our completion routine
2437 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2438 IoSetCompletionRoutine(Irp
, RamdiskIoCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
2441 // Call lower driver
2443 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2444 if (Status
== STATUS_PENDING
)
2446 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2447 Status
= Irp
->IoStatus
.Status
;
2451 // If it succeed to start, then, enable ourselve and we're up!
2453 if (NT_SUCCESS(Status
))
2455 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, TRUE
);
2456 DeviceExtension
->State
= RamdiskStateStarted
;
2459 Irp
->IoStatus
.Status
= Status
;
2462 case IRP_MN_QUERY_STOP_DEVICE
:
2464 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2467 case IRP_MN_CANCEL_STOP_DEVICE
:
2469 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2472 case IRP_MN_STOP_DEVICE
:
2474 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2477 case IRP_MN_QUERY_REMOVE_DEVICE
:
2479 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2482 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2484 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2487 case IRP_MN_REMOVE_DEVICE
:
2490 // Remove the proper device
2492 if (DeviceExtension
->Type
== RamdiskBus
)
2494 Status
= RamdiskRemoveBusDevice(DeviceObject
, Irp
);
2497 // Return here, lower device has already been called
2498 // And remove lock released. This is needed by the function.
2504 Status
= RamdiskDeleteDiskDevice(DeviceObject
, Irp
);
2507 // Complete the IRP here and return
2508 // Here again we don't have to release remove lock
2509 // This has already been done by the function.
2511 Irp
->IoStatus
.Status
= Status
;
2512 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2516 case IRP_MN_SURPRISE_REMOVAL
:
2518 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2521 case IRP_MN_QUERY_ID
:
2526 if (DeviceExtension
->Type
== RamdiskDrive
)
2528 Status
= RamdiskQueryId((PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
, Irp
);
2532 case IRP_MN_QUERY_BUS_INFORMATION
:
2537 if (DeviceExtension
->Type
== RamdiskDrive
)
2539 Status
= RamdiskQueryBusInformation(DeviceObject
, Irp
);
2545 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2548 case IRP_MN_QUERY_DEVICE_TEXT
:
2553 if (DeviceExtension
->Type
== RamdiskDrive
)
2555 Status
= RamdiskQueryDeviceText((PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
, Irp
);
2559 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2562 // Call our main routine
2564 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2566 QueryDeviceRelations
.Type
,
2569 goto ReleaseAndReturn
;
2571 case IRP_MN_QUERY_CAPABILITIES
:
2576 if (DeviceExtension
->Type
== RamdiskDrive
)
2578 Status
= RamdiskQueryCapabilities(DeviceObject
, Irp
);
2582 case IRP_MN_QUERY_RESOURCES
:
2583 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2586 // Complete immediately without touching it
2588 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2589 goto ReleaseAndReturn
;
2593 DPRINT1("Illegal IRP: %lx\n", Minor
);
2600 if (DeviceExtension
->Type
== RamdiskBus
)
2603 // Do we have an attached device?
2605 if (DeviceExtension
->AttachedDevice
)
2610 IoSkipCurrentIrpStackLocation(Irp
);
2611 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2616 // Release the lock and return status
2619 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2625 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2629 PIO_STACK_LOCATION IoStackLocation
;
2630 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2632 DeviceExtension
= DeviceObject
->DeviceExtension
;
2635 // If we have a device extension, take extra caution
2636 // with the lower driver
2638 if (DeviceExtension
!= NULL
)
2640 PoStartNextPowerIrp(Irp
);
2643 // Device has not been removed yet, so
2644 // pass to the attached/lower driver
2646 if (DeviceExtension
->State
< RamdiskStateBusRemoved
)
2648 IoSkipCurrentIrpStackLocation(Irp
);
2649 return PoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2652 // Otherwise, simply complete the IRP
2653 // Notifying that deletion is pending
2657 Irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
2658 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2659 return STATUS_DELETE_PENDING
;
2664 // Get stack and deal with minor functions
2666 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2667 switch (IoStackLocation
->MinorFunction
)
2669 case IRP_MN_SET_POWER
:
2671 // If setting device power state
2672 // it's all fine and return success
2674 if (DevicePowerState
)
2676 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2680 // Get appropriate status for return
2682 Status
= Irp
->IoStatus
.Status
;
2683 PoStartNextPowerIrp(Irp
);
2684 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2687 case IRP_MN_QUERY_POWER
:
2689 // We can obviously accept all states
2690 // So just return success
2693 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2694 PoStartNextPowerIrp(Irp
);
2695 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2700 // Just complete and save status for return
2702 Status
= Irp
->IoStatus
.Status
;
2703 PoStartNextPowerIrp(Irp
);
2704 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2713 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2717 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2719 DeviceExtension
= DeviceObject
->DeviceExtension
;
2722 // If we have a device extension, forward the IRP
2723 // to the attached device
2725 if (DeviceExtension
!= NULL
)
2727 IoSkipCurrentIrpStackLocation(Irp
);
2728 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2731 // Otherwise just complete the request
2732 // And return the status with which we complete it
2736 Status
= Irp
->IoStatus
.Status
;
2737 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2745 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2749 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2751 DeviceExtension
= DeviceObject
->DeviceExtension
;
2754 // Having a proper device is mandatory
2756 if (DeviceExtension
->State
> RamdiskStateStopped
)
2758 Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2763 // Acquire the remove lock
2765 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2766 if (!NT_SUCCESS(Status
))
2772 // Queue the IRP for worker
2774 Status
= SendIrpToThread(DeviceObject
, Irp
);
2775 if (Status
!= STATUS_PENDING
)
2781 // Release the remove lock
2783 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2787 Irp
->IoStatus
.Information
= 0;
2788 Irp
->IoStatus
.Status
= Status
;
2789 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2797 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2801 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
2803 DeviceExtension
= DeviceObject
->DeviceExtension
;
2806 // Ensure we have drive extension
2807 // Only perform flush on disks that have been created
2808 // from registry entries
2810 if (DeviceExtension
->Type
!= RamdiskDrive
||
2811 DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
2813 Irp
->IoStatus
.Information
= 0;
2814 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2815 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2816 return STATUS_SUCCESS
;
2820 // Queue the IRP for worker
2822 Status
= SendIrpToThread(DeviceObject
, Irp
);
2823 if (Status
!= STATUS_PENDING
)
2826 // Queueing failed - complete the IRP
2827 // and return failure
2829 Irp
->IoStatus
.Information
= 0;
2830 Irp
->IoStatus
.Status
= Status
;
2831 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2839 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2842 // Just release registry path if previously allocated
2844 if (DriverRegistryPath
.Buffer
)
2846 ExFreePoolWithTag(DriverRegistryPath
.Buffer
, 'dmaR');
2852 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2853 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2855 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2856 PDEVICE_OBJECT AttachedDevice
;
2858 UNICODE_STRING DeviceName
;
2859 PDEVICE_OBJECT DeviceObject
;
2862 // Only create the bus FDO once
2864 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2867 // Create the bus FDO
2869 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2870 Status
= IoCreateDevice(DriverObject
,
2871 sizeof(RAMDISK_BUS_EXTENSION
),
2873 FILE_DEVICE_BUS_EXTENDER
,
2874 FILE_DEVICE_SECURE_OPEN
,
2877 if (NT_SUCCESS(Status
))
2880 // Initialize the bus FDO extension
2882 DeviceExtension
= DeviceObject
->DeviceExtension
;
2883 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2884 sizeof(RAMDISK_BUS_EXTENSION
));
2887 // Set bus FDO flags
2889 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2892 // Setup the bus FDO extension
2894 DeviceExtension
->Type
= RamdiskBus
;
2895 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2896 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2900 InitializeListHead(&DeviceExtension
->DiskList
);
2901 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2902 DeviceExtension
->DeviceObject
= DeviceObject
;
2905 // Register the RAM disk device interface
2907 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2908 &RamdiskBusInterface
,
2910 &DeviceExtension
->BusDeviceName
);
2911 if (!NT_SUCCESS(Status
))
2916 IoDeleteDevice(DeviceObject
);
2921 // Attach us to the device stack
2923 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2924 PhysicalDeviceObject
);
2925 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2926 if (!AttachedDevice
)
2931 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2932 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2933 IoDeleteDevice(DeviceObject
);
2934 return STATUS_NO_SUCH_DEVICE
;
2938 // Bus FDO is initialized
2940 RamdiskBusFdo
= DeviceObject
;
2943 // Loop for loader block
2948 // Are we being booted from setup? Not yet supported
2950 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2956 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2957 Status
= STATUS_SUCCESS
;
2968 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2969 IN PUNICODE_STRING RegistryPath
)
2971 PCHAR BootDeviceName
, CommandLine
;
2972 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2974 DPRINT("RAM Disk Driver Initialized\n");
2977 // Query ramdisk parameters
2979 QueryParameters(RegistryPath
);
2982 // Save the registry path
2984 DriverRegistryPath
= *RegistryPath
;
2985 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2986 RegistryPath
->Length
+
2989 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2990 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2993 // Set device routines
2995 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2996 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2997 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2998 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2999 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
3000 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
3001 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
3002 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
3003 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
3004 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
3005 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
3006 DriverObject
->DriverUnload
= RamdiskUnload
;
3009 // Check for a loader block
3014 // Get the boot device name
3016 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
3020 // Check if we're booting from ramdisk
3022 if ((strlen(BootDeviceName
) >= 10) &&
3023 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
3026 // We'll have to tell the PnP Manager
3028 ReportDetectedDevice
= TRUE
;
3031 // Check for a command line
3033 CommandLine
= KeLoaderBlock
->LoadOptions
;
3037 // Check if this is an ISO boot
3039 if (strstr(CommandLine
, "RDEXPORTASCD"))
3042 // Remember for later
3044 ExportBootDiskAsCd
= TRUE
;
3048 // Check if this is PE boot
3050 if (strstr(CommandLine
, "MININT"))
3053 // Remember for later
3064 // Installing from Ramdisk isn't supported yet
3066 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
3069 // Are we reporting the device
3071 if (ReportDetectedDevice
)
3076 Status
= IoReportDetectedDevice(DriverObject
,
3077 InterfaceTypeUndefined
,
3083 &PhysicalDeviceObject
);
3084 if (NT_SUCCESS(Status
))
3087 // Create the device object
3089 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
3090 if (NT_SUCCESS(Status
))
3095 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
3096 Status
= STATUS_SUCCESS
;
3105 Status
= STATUS_SUCCESS
;