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
93 /* Inherited base class */
96 /* Data we get from the creator */
98 UNICODE_STRING GuidString
;
99 UNICODE_STRING SymbolicLinkName
;
101 RAMDISK_CREATE_OPTIONS DiskOptions
;
102 LARGE_INTEGER DiskLength
;
107 /* Data we get from the disk */
108 ULONG BytesPerSector
;
109 ULONG SectorsPerTrack
;
113 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
115 ULONG MaximumViewLength
;
116 ULONG MaximumPerDiskViewLength
;
117 ULONG ReportDetectedDevice
;
118 ULONG MarkRamdisksAsRemovable
;
119 ULONG MinimumViewCount
;
120 ULONG DefaultViewCount
;
121 ULONG MaximumViewCount
;
122 ULONG MinimumViewLength
;
123 ULONG DefaultViewLength
;
124 UNICODE_STRING DriverRegistryPath
;
125 BOOLEAN ExportBootDiskAsCd
;
127 PDEVICE_OBJECT RamdiskBusFdo
;
129 /* FUNCTIONS ******************************************************************/
133 QueryParameters(IN PUNICODE_STRING RegistryPath
)
135 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
136 RTL_QUERY_REGISTRY_TABLE QueryTable
[11];
139 MaximumViewLength
= 0x10000000u
;
140 MaximumPerDiskViewLength
= 0x10000000u
;
141 ReportDetectedDevice
= 0;
142 MarkRamdisksAsRemovable
= 0;
143 MinimumViewCount
= 2;
144 DefaultViewCount
= 16;
145 MaximumViewCount
= 64;
146 MinimumViewLength
= 0x10000u
;
147 DefaultViewLength
= 0x100000u
;
149 /* Setup the query table and query the registry */
150 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
151 QueryTable
[0].Flags
= 1;
152 QueryTable
[0].Name
= L
"Parameters";
153 QueryTable
[1].Flags
= 32;
154 QueryTable
[1].Name
= L
"ReportDetectedDevice";
155 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
156 QueryTable
[2].Flags
= 32;
157 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
158 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
159 QueryTable
[3].Flags
= 32;
160 QueryTable
[3].Name
= L
"MinimumViewCount";
161 QueryTable
[3].EntryContext
= &MinimumViewCount
;
162 QueryTable
[4].Flags
= 32;
163 QueryTable
[4].Name
= L
"DefaultViewCount";
164 QueryTable
[4].EntryContext
= &DefaultViewCount
;
165 QueryTable
[5].Flags
= 32;
166 QueryTable
[5].Name
= L
"MaximumViewCount";
167 QueryTable
[5].EntryContext
= &MaximumViewCount
;
168 QueryTable
[6].Flags
= 32;
169 QueryTable
[6].Name
= L
"MinimumViewLength";
170 QueryTable
[6].EntryContext
= &MinimumViewLength
;
171 QueryTable
[7].Flags
= 32;
172 QueryTable
[7].Name
= L
"DefaultViewLength";
173 QueryTable
[7].EntryContext
= &DefaultViewLength
;
174 QueryTable
[8].Flags
= 32;
175 QueryTable
[8].Name
= L
"MaximumViewLength";
176 QueryTable
[8].EntryContext
= &MaximumViewLength
;
177 QueryTable
[9].Flags
= 32;
178 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
179 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
180 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
181 RegistryPath
->Buffer
,
186 /* Parse minimum view count, cannot be bigger than 256 or smaller than 2 */
187 MinView
= MinimumViewCount
;
188 if (MinimumViewCount
>= 2)
190 if (MinimumViewCount
> 256) MinView
= 256;
196 MinimumViewCount
= MinView
;
198 /* Parse default view count, cannot be bigger than 256 or smaller than minimum */
199 DefView
= DefaultViewCount
;
200 if (DefaultViewCount
>= MinView
)
202 if (DefaultViewCount
> 256) DefView
= 256;
208 DefaultViewCount
= DefView
;
210 /* Parse maximum view count, cannot be bigger than 256 or smaller than default */
211 if (MaximumViewCount
>= DefView
)
213 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
217 MaximumViewCount
= DefView
;
220 /* Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB */
221 MinViewLength
= MinimumViewLength
;
222 if (MinimumViewLength
>= 0x10000)
224 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
228 MinViewLength
= 0x10000u
;
230 MinimumViewLength
= MinViewLength
;
232 /* Parse default view length, cannot be bigger than 1GB or smaller than minimum */
233 DefViewLength
= DefaultViewLength
;
234 if (DefaultViewLength
>= MinViewLength
)
236 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
240 DefViewLength
= MinViewLength
;
242 DefaultViewLength
= DefViewLength
;
244 /* Parse maximum view length, cannot be bigger than 1GB or smaller than default */
245 MaxViewLength
= MaximumViewLength
;
246 if (MaximumViewLength
>= DefViewLength
)
248 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
252 MaxViewLength
= DefViewLength
;
254 MaximumViewLength
= MaxViewLength
;
256 /* Parse maximum view length per disk, cannot be smaller than 16MB */
257 if (MaximumPerDiskViewLength
>= 0x1000000)
259 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
263 MaximumPerDiskViewLength
= 0x1000000u
;
269 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
270 IN LARGE_INTEGER Offset
,
272 OUT PULONG OutputLength
)
274 PHYSICAL_ADDRESS PhysicalAddress
;
278 LARGE_INTEGER ActualOffset
;
279 LARGE_INTEGER ActualPages
;
281 /* We only support boot disks for now */
282 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
284 /* Calculate the actual offset in the drive */
285 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
287 /* Convert to pages */
288 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
290 /* Now add the base page */
291 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
293 /* Calculate final amount of bytes */
294 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
296 /* Calculate pages spanned for the mapping */
297 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
299 /* And convert this back to bytes */
300 ActualLength
<<= PAGE_SHIFT
;
302 /* Get the offset within the page */
303 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
305 /* Map the I/O Space from the loader */
306 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
308 /* Return actual offset within the page as well as the length */
309 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
310 *OutputLength
= Length
;
316 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
317 IN PVOID BaseAddress
,
318 IN LARGE_INTEGER Offset
,
321 LARGE_INTEGER ActualOffset
;
325 /* We only support boot disks for now */
326 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
328 /* Calculate the actual offset in the drive */
329 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
331 /* Calculate pages spanned for the mapping */
332 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
334 /* And convert this back to bytes */
335 ActualLength
<<= PAGE_SHIFT
;
337 /* Get the offset within the page */
338 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
340 /* Calculate actual base address where we mapped this */
341 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
343 /* Unmap the I/O space we got from the loader */
344 MmUnmapIoSpace(BaseAddress
, ActualLength
);
349 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
350 IN PRAMDISK_CREATE_INPUT Input
,
351 IN BOOLEAN ValidateOnly
,
352 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
354 ULONG BasePage
, DiskType
, Length
;
357 PDEVICE_OBJECT DeviceObject
;
358 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
360 WCHAR LocalBuffer
[16];
361 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
362 PPACKED_BOOT_SECTOR BootSector
;
363 BIOS_PARAMETER_BLOCK BiosBlock
;
364 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
366 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
367 ULONG CylinderCount
, SizeByCylinders
;
369 /* Check if we're a boot RAM disk */
370 DiskType
= Input
->DiskType
;
371 if (DiskType
>= RAMDISK_BOOT_DISK
)
373 /* Check if we're an ISO */
374 if (DiskType
== RAMDISK_BOOT_DISK
)
376 /* NTLDR mounted us somewhere */
377 BasePage
= Input
->BasePage
;
378 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
380 /* Sanitize disk options */
381 Input
->Options
.Fixed
= TRUE
;
382 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
383 Input
->Options
.Readonly
;
384 Input
->Options
.Hidden
= FALSE
;
385 Input
->Options
.NoDosDevice
= FALSE
;
386 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
390 /* The only other possibility is a WIM disk */
391 if (DiskType
!= RAMDISK_WIM_DISK
)
394 return STATUS_INVALID_PARAMETER
;
397 /* Read the view count instead */
398 // ViewCount = Input->ViewCount;
400 /* Sanitize disk options */
401 Input
->Options
.Hidden
= FALSE
;
402 Input
->Options
.NoDosDevice
= FALSE
;
403 Input
->Options
.Readonly
= FALSE
;
404 Input
->Options
.NoDriveLetter
= TRUE
;
405 Input
->Options
.Fixed
= TRUE
;
408 /* Are we just validating and returning to the user? */
409 if (ValidateOnly
) return STATUS_SUCCESS
;
411 /* Build the GUID string */
412 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
413 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
416 Status
= STATUS_INSUFFICIENT_RESOURCES
;
420 /* Allocate our device name */
421 Length
= GuidString
.Length
+ 32;
422 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, Length
, 'dmaR');
426 Status
= STATUS_INSUFFICIENT_RESOURCES
;
430 /* Build the device name string */
431 DeviceName
.Buffer
= Buffer
;
432 DeviceName
.Length
= Length
- 2;
433 DeviceName
.MaximumLength
= Length
;
434 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
435 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
437 /* Create the drive device */
438 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
439 sizeof(RAMDISK_DRIVE_EXTENSION
),
441 (Input
->Options
.ExportAsCd
) ?
442 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
446 if (!NT_SUCCESS(Status
)) goto FailCreate
;
448 /* Grab the drive extension */
449 DriveExtension
= DeviceObject
->DeviceExtension
;
451 /* Check if we need a DOS device */
452 if (!Input
->Options
.NoDosDevice
)
454 /* Build the symbolic link name */
455 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
456 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
457 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
458 SymbolicLinkName
.MaximumLength
,
460 SymbolicLinkName
.Buffer
= Buffer
;
465 L
"\\GLOBAL??\\Ramdisk",
466 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
469 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
470 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
471 if (!NT_SUCCESS(Status
))
474 Input
->Options
.NoDosDevice
= TRUE
;
476 SymbolicLinkName
.Buffer
= NULL
;
482 Input
->Options
.NoDosDevice
= TRUE
;
485 /* Is this an ISO boot ramdisk? */
486 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
488 /* Does it need a drive letter? */
489 if (!Input
->Options
.NoDriveLetter
)
491 /* Build it and take over the existing symbolic link */
492 _snwprintf(LocalBuffer
,
494 L
"\\DosDevices\\%wc:",
496 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
497 IoDeleteSymbolicLink(&DriveString
);
498 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
500 /* Save the drive letter */
501 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
507 /* Setup the device object flags */
508 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
509 DeviceObject
->AlignmentRequirement
= 1;
511 /* Build the drive FDO */
512 *NewDriveExtension
= DriveExtension
;
513 DriveExtension
->Type
= RamdiskDrive
;
514 DiskLength
= Input
->DiskLength
;
515 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
516 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
, 'dmaR', 1, 0);
517 DriveExtension
->DriveDeviceName
= DeviceName
;
518 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
519 DriveExtension
->GuidString
= GuidString
;
520 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
521 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
522 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
523 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
524 DriveExtension
->DiskType
= Input
->DiskType
;
525 DriveExtension
->DiskOptions
= Input
->Options
;
526 DriveExtension
->DiskLength
= DiskLength
;
527 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
528 DriveExtension
->BasePage
= Input
->BasePage
;
529 DriveExtension
->BytesPerSector
= 0;
530 DriveExtension
->SectorsPerTrack
= 0;
531 DriveExtension
->NumberOfHeads
= 0;
533 /* Make sure we don't free it later */
534 DeviceName
.Buffer
= NULL
;
535 SymbolicLinkName
.Buffer
= NULL
;
536 GuidString
.Buffer
= NULL
;
538 /* Check if this is a boot disk, or a registry ram drive */
539 if (!(Input
->Options
.ExportAsCd
) &&
540 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
542 /* Not an ISO boot, but it's a boot FS -- map it to figure out the
544 CurrentOffset
.QuadPart
= 0;
545 BaseAddress
= RamdiskMapPages(DriveExtension
,
552 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
553 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
554 BytesPerSector
= BiosBlock
.BytesPerSector
;
555 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
556 Heads
= BiosBlock
.Heads
;
559 DriveExtension
->BytesPerSector
= BytesPerSector
;
560 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
561 DriveExtension
->NumberOfHeads
= Heads
;
564 CurrentOffset
.QuadPart
= 0;
565 RamdiskUnmapPages(DriveExtension
,
573 Status
= STATUS_INSUFFICIENT_RESOURCES
;
578 /* Check if the drive settings haven't been set yet */
579 if ((DriveExtension
->BytesPerSector
== 0) ||
580 (DriveExtension
->SectorsPerTrack
== 0) ||
581 (DriveExtension
->NumberOfHeads
== 0))
583 /* Check if this is a CD */
584 if (Input
->Options
.ExportAsCd
)
586 /* Setup partition parameters default for ISO 9660 */
587 DriveExtension
->BytesPerSector
= 2048;
588 DriveExtension
->SectorsPerTrack
= 32;
589 DriveExtension
->NumberOfHeads
= 64;
593 /* Setup partition parameters default for FAT */
594 DriveExtension
->BytesPerSector
= 512;
595 DriveExtension
->SectorsPerTrack
= 128;
596 DriveExtension
->NumberOfHeads
= 16;
600 /* Calculate the cylinder size */
601 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
602 DriveExtension
->SectorsPerTrack
*
603 DriveExtension
->NumberOfHeads
;
604 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
605 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
606 DriveExtension
->Cylinders
= CylinderCount
;
607 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
609 /* Align cylinder size up */
610 DriveExtension
->Cylinders
++;
613 /* Acquire the disk lock */
614 KeEnterCriticalRegion();
615 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
618 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
620 /* Release the lock */
621 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
622 KeLeaveCriticalRegion();
624 /* Clear init flag */
625 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
626 return STATUS_SUCCESS
;
630 UNIMPLEMENTED_DBGBREAK();
631 return STATUS_SUCCESS
;
636 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
638 IN BOOLEAN ValidateOnly
)
640 PRAMDISK_CREATE_INPUT Input
;
642 PRAMDISK_BUS_EXTENSION DeviceExtension
;
643 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
645 PWCHAR FileNameStart
, FileNameEnd
;
647 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
649 /* Get the device extension and our input data */
650 DeviceExtension
= DeviceObject
->DeviceExtension
;
651 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
652 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
654 /* Validate input parameters */
655 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
656 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
658 return STATUS_INVALID_PARAMETER
;
661 /* Validate the disk type */
662 DiskType
= Input
->DiskType
;
663 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
665 /* Look at the disk type */
666 if (DiskType
== RAMDISK_BOOT_DISK
)
668 /* We only allow this as an early-init boot */
669 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
671 /* Save command-line flags */
672 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
673 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
676 /* Validate the disk type */
677 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
679 /* If the type isn't CDFS, it has to at least be raw CD */
680 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
683 /* Check if this is an actual file */
684 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
686 /* Validate the file name */
687 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
688 FileNameEnd
= Input
->FileName
+ 1;
689 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
690 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
693 /* Create the actual device */
694 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
698 if (NT_SUCCESS(Status
))
700 /* Invalidate and set success */
701 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
702 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
711 RamdiskGetPartitionInfo(IN PIRP Irp
,
712 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
715 PPARTITION_INFORMATION PartitionInfo
;
717 LARGE_INTEGER Zero
= {{0, 0}};
719 PIO_STACK_LOCATION IoStackLocation
;
721 /* Validate the length */
722 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
723 if (IoStackLocation
->Parameters
.DeviceIoControl
.
724 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
727 Status
= STATUS_BUFFER_TOO_SMALL
;
728 Irp
->IoStatus
.Status
= Status
;
729 Irp
->IoStatus
.Information
= 0;
733 /* Map the partition table */
734 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
738 Status
= STATUS_INSUFFICIENT_RESOURCES
;
739 Irp
->IoStatus
.Status
= Status
;
740 Irp
->IoStatus
.Information
= 0;
744 /* Fill out the information */
745 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
746 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
747 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
748 DeviceExtension
->SectorsPerTrack
*
749 DeviceExtension
->NumberOfHeads
*
750 DeviceExtension
->Cylinders
;
751 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
752 PartitionInfo
->PartitionNumber
= 0;
753 PartitionInfo
->PartitionType
= *((PCHAR
)BaseAddress
+ 450);
754 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
755 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
756 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
758 PartitionInfo
->RewritePartition
= FALSE
;
760 /* Unmap the partition table */
761 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
764 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
765 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
766 return STATUS_SUCCESS
;
771 RamdiskSetPartitionInfo(IN PIRP Irp
,
772 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
777 PIO_STACK_LOCATION Stack
;
778 LARGE_INTEGER Zero
= {{0, 0}};
779 PPARTITION_INFORMATION PartitionInfo
;
781 /* First validate input */
782 Stack
= IoGetCurrentIrpStackLocation(Irp
);
783 if (Stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(PARTITION_INFORMATION
))
785 Status
= STATUS_INVALID_PARAMETER
;
790 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &BytesRead
);
791 if (BaseAddress
== NULL
)
793 Status
= STATUS_INSUFFICIENT_RESOURCES
;
797 /* Set the new partition type on partition 0, field system indicator */
798 PartitionInfo
= (PPARTITION_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
799 *((PCHAR
)BaseAddress
+ 450) = PartitionInfo
->PartitionType
;
802 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, BytesRead
);
803 Status
= STATUS_SUCCESS
;
806 Irp
->IoStatus
.Status
= Status
;
807 Irp
->IoStatus
.Information
= 0;
813 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
816 PRAMDISK_BUS_EXTENSION DeviceExtension
;
818 PIO_STACK_LOCATION IoStackLocation
;
821 /* Get the stack location */
822 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
824 /* Free the work item */
825 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
827 /* Grab the device extension and lock it */
828 DeviceExtension
= DeviceObject
->DeviceExtension
;
829 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
830 if (NT_SUCCESS(Status
))
832 /* Discriminate by major code */
833 switch (IoStackLocation
->MajorFunction
)
836 case IRP_MJ_DEVICE_CONTROL
:
838 /* Let's take a look at the IOCTL */
839 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
841 /* Ramdisk create request */
842 case FSCTL_CREATE_RAM_DISK
:
844 /* This time we'll do it for real */
845 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
849 case IOCTL_DISK_SET_PARTITION_INFO
:
851 Status
= RamdiskSetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
855 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
856 UNIMPLEMENTED_DBGBREAK("Get drive layout request\n");
859 case IOCTL_DISK_GET_PARTITION_INFO
:
861 Status
= RamdiskGetPartitionInfo(Irp
, (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
);
866 UNIMPLEMENTED_DBGBREAK("Invalid request\n");
874 /* Read or write request */
877 UNIMPLEMENTED_DBGBREAK("Read/Write request\n");
880 /* Internal request (SCSI?) */
881 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
882 UNIMPLEMENTED_DBGBREAK("SCSI request\n");
886 case IRP_MJ_FLUSH_BUFFERS
:
887 UNIMPLEMENTED_DBGBREAK("Flush request\n");
892 UNIMPLEMENTED_DBGBREAK("Invalid request: %lx\n",
893 IoStackLocation
->MajorFunction
);
897 /* Complete the I/O */
898 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
899 Irp
->IoStatus
.Status
= Status
;
900 Irp
->IoStatus
.Information
= 0;
901 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
906 Irp
->IoStatus
.Status
= Status
;
907 Irp
->IoStatus
.Information
= 0;
908 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
913 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
916 PIO_WORKITEM WorkItem
;
918 /* Mark the IRP pending */
919 IoMarkIrpPending(Irp
);
921 /* Allocate a work item */
922 WorkItem
= IoAllocateWorkItem(DeviceObject
);
926 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
927 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
928 return STATUS_PENDING
;
933 return STATUS_INSUFFICIENT_RESOURCES
;
939 RamdiskReadWriteReal(IN PIRP Irp
,
940 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
943 PVOID CurrentBase
, SystemVa
, BaseAddress
;
944 PIO_STACK_LOCATION IoStackLocation
;
945 LARGE_INTEGER CurrentOffset
;
946 ULONG BytesRead
, BytesLeft
, CopyLength
;
947 PVOID Source
, Destination
;
950 /* Get the MDL and check if it's mapped */
951 Mdl
= Irp
->MdlAddress
;
952 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
954 /* Use the mapped address */
955 SystemVa
= Mdl
->MappedSystemVa
;
959 /* Map it ourselves */
960 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
968 /* Make sure we were able to map it */
969 CurrentBase
= SystemVa
;
970 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
972 /* Initialize default */
973 Irp
->IoStatus
.Information
= 0;
975 /* Get the I/O Stack Location and capture the data */
976 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
977 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
978 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
979 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
981 /* Do the copy loop */
985 BaseAddress
= RamdiskMapPages(DeviceExtension
,
989 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
991 /* Update our lengths */
992 Irp
->IoStatus
.Information
+= BytesRead
;
993 CopyLength
= BytesRead
;
995 /* Check if this was a read or write */
996 Status
= STATUS_SUCCESS
;
997 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
999 /* Set our copy parameters */
1000 Destination
= CurrentBase
;
1001 Source
= BaseAddress
;
1004 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1006 /* Set our copy parameters */
1007 Destination
= BaseAddress
;
1008 Source
= CurrentBase
;
1011 RtlCopyMemory(Destination
, Source
, CopyLength
);
1015 /* Prepare us for failure */
1016 BytesLeft
= CopyLength
;
1017 Status
= STATUS_INVALID_PARAMETER
;
1020 /* Unmap the pages */
1021 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, CurrentOffset
, BytesRead
);
1023 /* Update offset and bytes left */
1024 BytesLeft
-= BytesRead
;
1025 CurrentOffset
.QuadPart
+= BytesRead
;
1026 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1028 /* Check if we are done */
1029 if (!BytesLeft
) return Status
;
1035 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1038 /* Complete the IRP */
1039 Irp
->IoStatus
.Information
= 1;
1040 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1041 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1042 return STATUS_SUCCESS
;
1047 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1050 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1052 // LARGE_INTEGER ByteOffset;
1053 PIO_STACK_LOCATION IoStackLocation
;
1054 NTSTATUS Status
, ReturnStatus
;
1056 /* Get the device extension and make sure this isn't a bus */
1057 DeviceExtension
= DeviceObject
->DeviceExtension
;
1058 if (DeviceExtension
->Type
== RamdiskBus
)
1061 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1065 /* Capture parameters */
1066 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1067 // Length = IoStackLocation->Parameters.Read.Length;
1068 // ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
1070 /* FIXME: Validate offset */
1072 /* FIXME: Validate sector */
1074 /* Validate write */
1075 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1076 (DeviceExtension
->DiskOptions
.Readonly
))
1078 /* Fail, this is read-only */
1079 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1083 /* See if we want to do this sync or async */
1084 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1087 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1091 /* Queue it to the worker */
1092 Status
= SendIrpToThread(DeviceObject
, Irp
);
1093 ReturnStatus
= STATUS_PENDING
;
1095 /* Check if we're pending or not */
1096 if (Status
!= STATUS_PENDING
)
1099 /* Complete the IRP */
1100 Irp
->IoStatus
.Status
= Status
;
1101 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1102 ReturnStatus
= Status
;
1105 /* Return to caller */
1106 return ReturnStatus
;
1111 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1115 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1116 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1117 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1120 PDISK_GEOMETRY DiskGeometry
;
1122 /* Grab the remove lock */
1123 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1124 if (!NT_SUCCESS(Status
))
1127 Irp
->IoStatus
.Information
= 0;
1128 Irp
->IoStatus
.Status
= Status
;
1129 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1133 /* Setup some defaults */
1134 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1137 /* Check if this is an bus device or the drive */
1138 if (DeviceExtension
->Type
== RamdiskBus
)
1140 /* Check what the request is */
1141 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1143 /* Request to create a ramdisk */
1144 case FSCTL_CREATE_RAM_DISK
:
1147 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1148 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1154 /* We don't handle anything else yet */
1155 UNIMPLEMENTED_DBGBREAK("FSCTL: 0x%lx is UNSUPPORTED!\n",
1156 IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1162 /* Check what the request is */
1163 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1165 case IOCTL_DISK_CHECK_VERIFY
:
1166 case IOCTL_STORAGE_CHECK_VERIFY
:
1167 case IOCTL_STORAGE_CHECK_VERIFY2
:
1168 case IOCTL_CDROM_CHECK_VERIFY
:
1170 /* Just pretend it's OK, don't do more */
1171 Status
= STATUS_SUCCESS
;
1175 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1176 case IOCTL_DISK_GET_MEDIA_TYPES
:
1177 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1178 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1180 /* Validate the length */
1181 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1182 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1184 /* Invalid length */
1185 Status
= STATUS_BUFFER_TOO_SMALL
;
1190 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1191 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1192 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1193 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1194 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1195 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1196 FixedMedia
: RemovableMedia
;
1199 Status
= STATUS_SUCCESS
;
1200 Information
= sizeof(DISK_GEOMETRY
);
1204 case IOCTL_CDROM_READ_TOC
:
1206 /* Validate the length */
1207 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1208 OutputBufferLength
< sizeof(CDROM_TOC
))
1210 /* Invalid length */
1211 Status
= STATUS_BUFFER_TOO_SMALL
;
1216 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1217 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1221 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1222 Toc
->FirstTrack
= 1;
1224 Toc
->TrackData
[0].Adr
= 1;
1225 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1226 Toc
->TrackData
[0].TrackNumber
= 1;
1229 Status
= STATUS_SUCCESS
;
1230 Information
= RAMDISK_TOC_SIZE
;
1234 case IOCTL_DISK_SET_PARTITION_INFO
:
1236 Status
= RamdiskSetPartitionInfo(Irp
, DriveExtension
);
1240 case IOCTL_DISK_GET_PARTITION_INFO
:
1242 /* Validate the length */
1243 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1244 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1246 /* Invalid length */
1247 Status
= STATUS_BUFFER_TOO_SMALL
;
1251 /* Check if we need to do this sync or async */
1252 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1254 /* Call the helper function */
1255 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1259 /* Do it asynchronously later */
1264 Information
= Irp
->IoStatus
.Information
;
1268 case IOCTL_DISK_GET_LENGTH_INFO
:
1270 PGET_LENGTH_INFORMATION LengthInformation
= Irp
->AssociatedIrp
.SystemBuffer
;
1272 /* Validate the length */
1273 if (IoStackLocation
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GET_LENGTH_INFORMATION
))
1275 /* Invalid length */
1276 Status
= STATUS_BUFFER_TOO_SMALL
;
1281 LengthInformation
->Length
= DriveExtension
->DiskLength
;
1284 Status
= STATUS_SUCCESS
;
1285 Information
= sizeof(GET_LENGTH_INFORMATION
);
1288 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1290 PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION GptInformation
;
1292 /* Validate the length */
1293 if (IoStackLocation
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION
))
1295 /* Invalid length */
1296 Status
= STATUS_BUFFER_TOO_SMALL
;
1301 GptInformation
= Irp
->AssociatedIrp
.SystemBuffer
;
1302 GptInformation
->GptAttributes
= 0;
1304 /* Translate the Attributes */
1305 if (DriveExtension
->DiskOptions
.Readonly
)
1306 GptInformation
->GptAttributes
|= GPT_BASIC_DATA_ATTRIBUTE_READ_ONLY
;
1307 if (DriveExtension
->DiskOptions
.Hidden
)
1308 GptInformation
->GptAttributes
|= GPT_BASIC_DATA_ATTRIBUTE_HIDDEN
;
1309 if (DriveExtension
->DiskOptions
.NoDriveLetter
)
1310 GptInformation
->GptAttributes
|= GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER
;
1313 Status
= STATUS_SUCCESS
;
1314 Information
= sizeof(VOLUME_GET_GPT_ATTRIBUTES_INFORMATION
);
1318 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1319 case IOCTL_DISK_IS_WRITABLE
:
1320 case IOCTL_SCSI_MINIPORT
:
1321 case IOCTL_STORAGE_QUERY_PROPERTY
:
1322 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1323 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1324 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1325 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1326 case IOCTL_VOLUME_OFFLINE
:
1328 UNIMPLEMENTED_DBGBREAK("IOCTL: 0x%lx is UNIMPLEMENTED!\n",
1329 IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1335 /* Drive code not emulated */
1336 DPRINT1("IOCTL: 0x%lx is UNSUPPORTED!\n",
1337 IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1342 /* If requests drop down here, we just return them complete them */
1343 goto CompleteRequest
;
1346 /* Queue the request to our worker thread */
1348 Status
= SendIrpToThread(DeviceObject
, Irp
);
1351 /* Release the lock */
1352 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1353 if (Status
!= STATUS_PENDING
)
1355 /* Complete the request */
1356 Irp
->IoStatus
.Status
= Status
;
1357 Irp
->IoStatus
.Information
= Information
;
1358 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1367 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1368 IN PDEVICE_OBJECT DeviceObject
,
1371 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1372 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1373 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1374 ULONG Count
, DiskCount
, FinalCount
;
1375 PLIST_ENTRY ListHead
, NextEntry
;
1376 PDEVICE_OBJECT
* DriveDeviceObject
;
1377 RAMDISK_DEVICE_STATE State
;
1379 /* Get the device extension and check if this is a drive */
1380 DeviceExtension
= DeviceObject
->DeviceExtension
;
1381 if (DeviceExtension
->Type
== RamdiskDrive
)
1384 PDEVICE_RELATIONS DeviceRelations
;
1386 /* We're a child device, only handle target device relations */
1387 if (Type
!= TargetDeviceRelation
)
1389 Status
= Irp
->IoStatus
.Status
;
1390 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1394 /* Allocate a buffer big enough to contain only one DO */
1395 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1396 sizeof(*DeviceRelations
),
1398 if (DeviceRelations
!= NULL
)
1400 /* Reference the DO and add it to the buffer */
1401 ObReferenceObject(DeviceObject
);
1402 DeviceRelations
->Objects
[0] = DeviceObject
;
1403 DeviceRelations
->Count
= 1;
1404 Status
= STATUS_SUCCESS
;
1408 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1411 /* Return our processing & complete */
1412 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1413 Irp
->IoStatus
.Status
= Status
;
1414 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1418 /* We don't handle anything but bus relations */
1419 if (Type
!= BusRelations
) goto PassToNext
;
1421 /* Acquire the disk list lock */
1422 KeEnterCriticalRegion();
1423 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1425 /* Did a device already fill relations? */
1426 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1427 if (DeviceRelations
)
1430 Count
= DeviceRelations
->Count
;
1434 /* We're the first */
1438 /* Now loop our drives */
1440 ListHead
= &DeviceExtension
->DiskList
;
1441 NextEntry
= ListHead
->Flink
;
1442 while (NextEntry
!= ListHead
)
1444 /* As long as it wasn't removed, count it in */
1445 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1446 RAMDISK_DRIVE_EXTENSION
,
1448 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1450 /* Move to the next one */
1451 NextEntry
= NextEntry
->Flink
;
1454 /* Now we know our final count */
1455 FinalCount
= Count
+ DiskCount
;
1457 /* Allocate the structure */
1458 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1459 FIELD_OFFSET(DEVICE_RELATIONS
,
1462 sizeof(PDEVICE_OBJECT
),
1464 if (!OurDeviceRelations
)
1467 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1468 KeLeaveCriticalRegion();
1469 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1470 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1471 return STATUS_INSUFFICIENT_RESOURCES
;
1474 /* Check if we already had some relations */
1478 RtlCopyMemory(OurDeviceRelations
->Objects
,
1479 DeviceRelations
->Objects
,
1480 Count
* sizeof(PDEVICE_OBJECT
));
1483 /* Save the count */
1484 OurDeviceRelations
->Count
= FinalCount
;
1486 /* Now loop our drives again */
1487 ListHead
= &DeviceExtension
->DiskList
;
1488 NextEntry
= ListHead
->Flink
;
1489 while (NextEntry
!= ListHead
)
1491 /* Go to the end of the list */
1492 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1494 /* Get the drive state */
1495 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1496 RAMDISK_DRIVE_EXTENSION
,
1498 State
= DriveExtension
->State
;
1500 /* If it was removed or enumerated, we don't touch the device object */
1501 if (State
>= RamdiskStateBusRemoved
)
1503 /* If it was removed, we still have to keep track of this though */
1504 if (State
== RamdiskStateBusRemoved
)
1506 /* Mark it as enumerated now, but don't actually reference it */
1507 DriveExtension
->State
= RamdiskStateEnumerated
;
1512 /* First time it's enumerated, reference the device object */
1513 ObReferenceObject(DriveExtension
->DeviceObject
);
1515 /* Save the object pointer and move on */
1516 *DriveDeviceObject
++ = DriveExtension
->PhysicalDeviceObject
;
1519 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1521 /* Move to the next one */
1522 NextEntry
= NextEntry
->Flink
;
1525 /* Release the lock */
1526 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1527 KeLeaveCriticalRegion();
1529 /* Cleanup old relations */
1530 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1532 /* Complete our IRP */
1533 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1534 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1536 /* Pass to the next driver */
1538 IoCopyCurrentIrpStackLocationToNext(Irp
);
1539 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1544 RamdiskDeleteDiskDevice(IN PDEVICE_OBJECT DeviceObject
,
1547 UNIMPLEMENTED_DBGBREAK();
1548 return STATUS_SUCCESS
;
1553 RamdiskRemoveBusDevice(IN PDEVICE_OBJECT DeviceObject
,
1557 PLIST_ENTRY ListHead
, NextEntry
;
1558 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1559 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1561 DeviceExtension
= DeviceObject
->DeviceExtension
;
1563 /* Acquire disks list lock */
1564 KeEnterCriticalRegion();
1565 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1567 /* Loop over drives */
1568 ListHead
= &DeviceExtension
->DiskList
;
1569 NextEntry
= ListHead
->Flink
;
1570 while (NextEntry
!= ListHead
)
1572 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1573 RAMDISK_DRIVE_EXTENSION
,
1576 /* Delete the disk */
1577 IoAcquireRemoveLock(&DriveExtension
->RemoveLock
, NULL
);
1578 RamdiskDeleteDiskDevice(DriveExtension
->PhysicalDeviceObject
, NULL
);
1580 /* RamdiskDeleteDiskDevice releases list lock, so reacquire it */
1581 KeEnterCriticalRegion();
1582 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1585 /* Release disks list lock */
1586 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1587 KeLeaveCriticalRegion();
1589 /* Prepare to pass to the lower driver */
1590 IoSkipCurrentIrpStackLocation(Irp
);
1591 /* Here everything went fine */
1592 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1594 /* Call lower driver */
1595 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1598 DeviceExtension
->State
= RamdiskStateBusRemoved
;
1600 /* Release the lock and ensure that everyone has finished its job before
1601 * we continue. The lock has been acquired by the dispatcher */
1602 IoReleaseRemoveLockAndWait(&DeviceExtension
->RemoveLock
, Irp
);
1604 /* If there's a drive name */
1605 if (DeviceExtension
->DriveDeviceName
.Buffer
)
1607 /* Inform it's going to be disabled and free the drive name */
1608 IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, FALSE
);
1609 RtlFreeUnicodeString(&DeviceExtension
->DriveDeviceName
);
1612 /* Part from the stack, detach from lower device */
1613 IoDetachDevice(DeviceExtension
->AttachedDevice
);
1615 /* Finally, delete device */
1616 RamdiskBusFdo
= NULL
;
1617 IoDeleteDevice(DeviceObject
);
1619 /* Return status from lower driver */
1625 RamdiskQueryId(IN PRAMDISK_DRIVE_EXTENSION DriveExtension
,
1629 PIO_STACK_LOCATION IoStackLocation
;
1630 PWSTR OutputString
= NULL
;
1633 Status
= STATUS_SUCCESS
;
1634 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1636 /* Get what is being queried */
1637 switch (IoStackLocation
->Parameters
.QueryId
.IdType
)
1639 case BusQueryDeviceID
:
1641 /* Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
1642 * In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
1643 * chars to store Ramdisk\RamVolume instead */
1644 StringLength
= 4 * (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
) + sizeof(L
"Ramdisk\\RamDisk");
1645 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
1646 if (OutputString
== NULL
)
1648 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1652 wcsncpy(OutputString
, L
"Ramdisk\\", StringLength
/ sizeof(WCHAR
));
1653 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
1655 wcsncat(OutputString
, L
"RamVolume", StringLength
/ sizeof(WCHAR
));
1659 wcsncat(OutputString
, L
"RamDisk", StringLength
/ sizeof(WCHAR
));
1665 case BusQueryHardwareIDs
:
1667 /* Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
1668 * In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
1669 * chars to store Ramdisk\RamVolume instead
1670 * We also need an extra char, because it is required that the string
1671 * is null-terminated twice */
1672 StringLength
= 4 * (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
) +
1673 sizeof(UNICODE_NULL
) + sizeof(L
"Ramdisk\\RamDisk");
1674 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
1675 if (OutputString
== NULL
)
1677 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1681 wcsncpy(OutputString
, L
"Ramdisk\\", StringLength
/ sizeof(WCHAR
));
1682 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
1684 wcsncat(OutputString
, L
"RamVolume", StringLength
/ sizeof(WCHAR
));
1688 wcsncat(OutputString
, L
"RamDisk", StringLength
/ sizeof(WCHAR
));
1690 OutputString
[(StringLength
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
1695 case BusQueryCompatibleIDs
:
1697 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
1699 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1703 StringLength
= sizeof(L
"GenDisk");
1704 OutputString
= ExAllocatePoolWithTag(PagedPool
, StringLength
, 'dmaR');
1705 if (OutputString
== NULL
)
1707 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1711 wcsncpy(OutputString
, L
"GenDisk", StringLength
/ sizeof(WCHAR
));
1712 OutputString
[(StringLength
/ sizeof(WCHAR
)) - 1] = UNICODE_NULL
;
1717 case BusQueryInstanceID
:
1719 OutputString
= ExAllocatePoolWithTag(PagedPool
,
1720 DriveExtension
->GuidString
.MaximumLength
,
1722 if (OutputString
== NULL
)
1724 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1728 wcsncpy(OutputString
,
1729 DriveExtension
->GuidString
.Buffer
,
1730 DriveExtension
->GuidString
.MaximumLength
/ sizeof(WCHAR
));
1735 case BusQueryDeviceSerialNumber
:
1736 case BusQueryContainerID
:
1743 Irp
->IoStatus
.Status
= Status
;
1744 Irp
->IoStatus
.Information
= (ULONG_PTR
)OutputString
;
1745 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1751 RamdiskQueryCapabilities(IN PDEVICE_OBJECT DeviceObject
,
1755 PIO_STACK_LOCATION IoStackLocation
;
1756 PDEVICE_CAPABILITIES DeviceCapabilities
;
1757 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1759 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1760 DeviceCapabilities
= IoStackLocation
->Parameters
.DeviceCapabilities
.Capabilities
;
1761 DriveExtension
= DeviceObject
->DeviceExtension
;
1763 /* Validate our input buffer */
1764 if (DeviceCapabilities
->Version
!= 1 ||
1765 DeviceCapabilities
->Size
< sizeof(DEVICE_CAPABILITIES
))
1767 Status
= STATUS_UNSUCCESSFUL
;
1771 /* And set everything we know about our capabilities */
1772 DeviceCapabilities
->Removable
= MarkRamdisksAsRemovable
;
1773 DeviceCapabilities
->UniqueID
= TRUE
;
1774 DeviceCapabilities
->SilentInstall
= TRUE
;
1775 DeviceCapabilities
->RawDeviceOK
= TRUE
;
1776 DeviceCapabilities
->SurpriseRemovalOK
= (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
);
1777 DeviceCapabilities
->NoDisplayInUI
= TRUE
;
1778 Status
= STATUS_SUCCESS
;
1781 Irp
->IoStatus
.Status
= Status
;
1782 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1788 RamdiskQueryDeviceText(IN PRAMDISK_DRIVE_EXTENSION DriveExtension
,
1792 PIO_STACK_LOCATION IoStackLocation
;
1793 DEVICE_TEXT_TYPE DeviceTextType
;
1794 PWSTR OutputString
= NULL
;
1796 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1797 DeviceTextType
= IoStackLocation
->Parameters
.QueryDeviceText
.DeviceTextType
;
1798 Status
= STATUS_SUCCESS
;
1800 /* Just copy our constants, according to the input */
1801 switch (DeviceTextType
)
1803 case DeviceTextDescription
:
1805 OutputString
= ExAllocatePoolWithTag(PagedPool
, sizeof(L
"RamDisk"), 'dmaR');
1806 if (OutputString
== NULL
)
1808 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1812 wcsncpy(OutputString
, L
"RamDisk", sizeof(L
"RamDisk") / sizeof(WCHAR
));
1817 case DeviceTextLocationInformation
:
1819 OutputString
= ExAllocatePoolWithTag(PagedPool
, sizeof(L
"RamDisk\\0"), 'dmaR');
1820 if (OutputString
== NULL
)
1822 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1826 wcsncpy(OutputString
, L
"RamDisk\\0", sizeof(L
"RamDisk\\0") / sizeof(WCHAR
));
1832 Irp
->IoStatus
.Status
= Status
;
1833 Irp
->IoStatus
.Information
= (ULONG_PTR
)OutputString
;
1834 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1840 RamdiskQueryBusInformation(IN PDEVICE_OBJECT DeviceObject
,
1843 PPNP_BUS_INFORMATION PnpBusInfo
;
1844 NTSTATUS Status
= STATUS_SUCCESS
;
1846 /* Allocate output memory */
1847 PnpBusInfo
= ExAllocatePoolWithTag(PagedPool
, sizeof(*PnpBusInfo
), 'dmaR');
1848 if (PnpBusInfo
== NULL
)
1850 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1854 /* Copy our bus GUID and set our legacy type */
1855 RtlCopyMemory(&PnpBusInfo
->BusTypeGuid
, &GUID_BUS_TYPE_RAMDISK
, sizeof(GUID
));
1856 PnpBusInfo
->LegacyBusType
= PNPBus
;
1857 PnpBusInfo
->BusNumber
= 0;
1860 Irp
->IoStatus
.Status
= Status
;
1861 Irp
->IoStatus
.Information
= (ULONG_PTR
)PnpBusInfo
;
1862 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1868 RamdiskIoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject
,
1873 /* Just set the event to unlock caller */
1874 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
1876 return STATUS_MORE_PROCESSING_REQUIRED
;
1881 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1884 PIO_STACK_LOCATION IoStackLocation
;
1885 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1890 /* Get the device extension and stack location */
1891 DeviceExtension
= DeviceObject
->DeviceExtension
;
1892 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1893 Minor
= IoStackLocation
->MinorFunction
;
1895 /* Check if the bus is removed */
1896 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1898 /* Only remove-device and query-id are allowed */
1899 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) && (Minor
!= IRP_MN_QUERY_ID
))
1901 /* Fail anything else */
1902 Status
= STATUS_NO_SUCH_DEVICE
;
1903 Irp
->IoStatus
.Status
= Status
;
1904 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1909 /* Acquire the remove lock */
1910 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1911 if (!NT_SUCCESS(Status
))
1914 Irp
->IoStatus
.Information
= 0;
1915 Irp
->IoStatus
.Status
= Status
;
1916 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1920 /* Query the IRP type */
1923 case IRP_MN_START_DEVICE
:
1925 if (DeviceExtension
->Type
== RamdiskDrive
)
1928 DEVICE_INSTALL_STATE InstallState
;
1929 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
;
1931 /* If we already have a drive name, free it */
1932 if (DriveExtension
->DriveDeviceName
.Buffer
)
1934 ExFreePool(DriveExtension
->DriveDeviceName
.Buffer
);
1937 /* Register our device interface */
1938 if (DriveExtension
->DiskType
!= RAMDISK_REGISTRY_DISK
)
1940 Status
= IoRegisterDeviceInterface(DeviceObject
,
1941 &GUID_DEVINTERFACE_VOLUME
,
1943 &DriveExtension
->DriveDeviceName
);
1947 Status
= IoRegisterDeviceInterface(DeviceObject
,
1948 &RamdiskDiskInterface
,
1950 &DriveExtension
->DriveDeviceName
);
1953 /* If we were asked not to assign a drive letter or if getting
1954 * a name failed, just return saying we're now started */
1955 if (DriveExtension
->DiskOptions
.NoDriveLetter
||
1956 DriveExtension
->DriveDeviceName
.Buffer
== NULL
)
1958 DriveExtension
->State
= RamdiskStateStarted
;
1959 Irp
->IoStatus
.Status
= Status
;
1963 /* Now get our installation state */
1964 Status
= IoGetDeviceProperty(DeviceObject
,
1965 DevicePropertyInstallState
,
1966 sizeof(InstallState
),
1969 /* If querying the information failed, assume success */
1970 if (!NT_SUCCESS(Status
))
1972 InstallState
= InstallStateInstalled
;
1975 /* If we were properly installed, then, enable the interface */
1976 if (InstallState
== InstallStateInstalled
)
1978 Status
= IoSetDeviceInterfaceState(&DriveExtension
->DriveDeviceName
, TRUE
);
1981 /* We're fine & up */
1982 DriveExtension
->State
= RamdiskStateStarted
;
1983 Irp
->IoStatus
.Status
= Status
;
1987 /* Prepare next stack to pass it down */
1988 IoCopyCurrentIrpStackLocationToNext(Irp
);
1990 /* Initialize our notification event & our completion routine */
1991 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1992 IoSetCompletionRoutine(Irp
, RamdiskIoCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
1994 /* Call lower driver */
1995 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1996 if (Status
== STATUS_PENDING
)
1998 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1999 Status
= Irp
->IoStatus
.Status
;
2002 /* If it succeed to start then enable ourselves and we're up! */
2003 if (NT_SUCCESS(Status
))
2005 Status
= IoSetDeviceInterfaceState(&DeviceExtension
->DriveDeviceName
, TRUE
);
2006 DeviceExtension
->State
= RamdiskStateStarted
;
2009 Irp
->IoStatus
.Status
= Status
;
2013 case IRP_MN_QUERY_STOP_DEVICE
:
2014 case IRP_MN_CANCEL_STOP_DEVICE
:
2015 case IRP_MN_STOP_DEVICE
:
2016 case IRP_MN_QUERY_REMOVE_DEVICE
:
2017 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2019 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2023 case IRP_MN_REMOVE_DEVICE
:
2025 /* Remove the proper device */
2026 if (DeviceExtension
->Type
== RamdiskBus
)
2028 Status
= RamdiskRemoveBusDevice(DeviceObject
, Irp
);
2030 /* Return here, lower device has already been called
2031 * And remove lock released. This is needed by the function. */
2036 Status
= RamdiskDeleteDiskDevice(DeviceObject
, Irp
);
2038 /* Complete the IRP here and return
2039 * Here again we don't have to release remove lock
2040 * This has already been done by the function. */
2041 Irp
->IoStatus
.Status
= Status
;
2042 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2047 case IRP_MN_SURPRISE_REMOVAL
:
2048 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2051 case IRP_MN_QUERY_ID
:
2053 /* Are we a drive? */
2054 if (DeviceExtension
->Type
== RamdiskDrive
)
2056 Status
= RamdiskQueryId((PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
, Irp
);
2061 case IRP_MN_QUERY_BUS_INFORMATION
:
2063 /* Are we a drive? */
2064 if (DeviceExtension
->Type
== RamdiskDrive
)
2066 Status
= RamdiskQueryBusInformation(DeviceObject
, Irp
);
2072 UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor
);
2075 case IRP_MN_QUERY_DEVICE_TEXT
:
2077 /* Are we a drive? */
2078 if (DeviceExtension
->Type
== RamdiskDrive
)
2080 Status
= RamdiskQueryDeviceText((PRAMDISK_DRIVE_EXTENSION
)DeviceExtension
, Irp
);
2085 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2087 /* Call our main routine */
2088 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2090 QueryDeviceRelations
.Type
,
2093 goto ReleaseAndReturn
;
2096 case IRP_MN_QUERY_CAPABILITIES
:
2098 /* Are we a drive? */
2099 if (DeviceExtension
->Type
== RamdiskDrive
)
2101 Status
= RamdiskQueryCapabilities(DeviceObject
, Irp
);
2106 case IRP_MN_QUERY_RESOURCES
:
2107 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2109 /* Complete immediately without touching it */
2110 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2111 goto ReleaseAndReturn
;
2115 DPRINT1("Illegal IRP: %lx\n", Minor
);
2119 /* Are we the bus? */
2120 if (DeviceExtension
->Type
== RamdiskBus
)
2122 /* Do we have an attached device? */
2123 if (DeviceExtension
->AttachedDevice
)
2125 /* Forward the IRP */
2126 IoSkipCurrentIrpStackLocation(Irp
);
2127 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2131 /* Release the lock and return status */
2133 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2139 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2143 PIO_STACK_LOCATION IoStackLocation
;
2144 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2146 DeviceExtension
= DeviceObject
->DeviceExtension
;
2148 /* If we have a device extension, take extra caution with the lower driver */
2149 if (DeviceExtension
!= NULL
)
2151 PoStartNextPowerIrp(Irp
);
2153 /* Device has not been removed yet, so pass to the attached/lower driver */
2154 if (DeviceExtension
->State
< RamdiskStateBusRemoved
)
2156 IoSkipCurrentIrpStackLocation(Irp
);
2157 return PoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2159 /* Otherwise, simply complete the IRP notifying that deletion is pending */
2162 Irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
2163 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2164 return STATUS_DELETE_PENDING
;
2168 /* Get stack and deal with minor functions */
2169 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
2170 switch (IoStackLocation
->MinorFunction
)
2172 case IRP_MN_SET_POWER
:
2174 /* If setting device power state it's all fine and return success */
2175 if (DevicePowerState
)
2177 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2180 /* Get appropriate status for return */
2181 Status
= Irp
->IoStatus
.Status
;
2182 PoStartNextPowerIrp(Irp
);
2183 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2187 case IRP_MN_QUERY_POWER
:
2189 /* We can obviously accept all states so just return success */
2190 Status
= Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2191 PoStartNextPowerIrp(Irp
);
2192 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2198 /* Just complete and save status for return */
2199 Status
= Irp
->IoStatus
.Status
;
2200 PoStartNextPowerIrp(Irp
);
2201 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2211 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2215 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2217 DeviceExtension
= DeviceObject
->DeviceExtension
;
2219 /* If we have a device extension, forward the IRP to the attached device */
2220 if (DeviceExtension
!= NULL
)
2222 IoSkipCurrentIrpStackLocation(Irp
);
2223 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2225 /* Otherwise just complete the request
2226 * And return the status with which we complete it */
2229 Status
= Irp
->IoStatus
.Status
;
2230 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2238 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2242 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2244 DeviceExtension
= DeviceObject
->DeviceExtension
;
2246 /* Having a proper device is mandatory */
2247 if (DeviceExtension
->State
> RamdiskStateStopped
)
2249 Status
= STATUS_DEVICE_DOES_NOT_EXIST
;
2253 /* Acquire the remove lock */
2254 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2255 if (!NT_SUCCESS(Status
))
2260 /* Queue the IRP for worker */
2261 Status
= SendIrpToThread(DeviceObject
, Irp
);
2262 if (Status
!= STATUS_PENDING
)
2267 /* Release the remove lock */
2268 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2272 Irp
->IoStatus
.Information
= 0;
2273 Irp
->IoStatus
.Status
= Status
;
2274 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2282 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2286 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
2288 DeviceExtension
= DeviceObject
->DeviceExtension
;
2290 /* Ensure we have drive extension
2291 * Only perform flush on disks that have been created
2292 * from registry entries */
2293 if (DeviceExtension
->Type
!= RamdiskDrive
||
2294 DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
2296 Irp
->IoStatus
.Information
= 0;
2297 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2298 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2299 return STATUS_SUCCESS
;
2302 /* Queue the IRP for worker */
2303 Status
= SendIrpToThread(DeviceObject
, Irp
);
2304 if (Status
!= STATUS_PENDING
)
2306 /* Queuing failed - complete the IRP and return failure */
2307 Irp
->IoStatus
.Information
= 0;
2308 Irp
->IoStatus
.Status
= Status
;
2309 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2317 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2319 /* Just release registry path if previously allocated */
2320 if (DriverRegistryPath
.Buffer
)
2322 ExFreePoolWithTag(DriverRegistryPath
.Buffer
, 'dmaR');
2328 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2329 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2331 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2332 PDEVICE_OBJECT AttachedDevice
;
2334 UNICODE_STRING DeviceName
;
2335 PDEVICE_OBJECT DeviceObject
;
2337 /* Only create the bus FDO once */
2338 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2340 /* Create the bus FDO */
2341 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2342 Status
= IoCreateDevice(DriverObject
,
2343 sizeof(RAMDISK_BUS_EXTENSION
),
2345 FILE_DEVICE_BUS_EXTENDER
,
2346 FILE_DEVICE_SECURE_OPEN
,
2349 if (NT_SUCCESS(Status
))
2351 /* Initialize the bus FDO extension */
2352 DeviceExtension
= DeviceObject
->DeviceExtension
;
2353 RtlZeroMemory(DeviceExtension
, sizeof(*DeviceExtension
));
2355 /* Set bus FDO flags */
2356 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2358 /* Setup the bus FDO extension */
2359 DeviceExtension
->Type
= RamdiskBus
;
2360 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2361 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
, 'dmaR', 1, 0);
2362 InitializeListHead(&DeviceExtension
->DiskList
);
2363 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2364 DeviceExtension
->DeviceObject
= DeviceObject
;
2366 /* Register the RAM disk device interface */
2367 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2368 &RamdiskBusInterface
,
2370 &DeviceExtension
->BusDeviceName
);
2371 if (!NT_SUCCESS(Status
))
2374 IoDeleteDevice(DeviceObject
);
2378 /* Attach us to the device stack */
2379 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2380 PhysicalDeviceObject
);
2381 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2382 if (!AttachedDevice
)
2385 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2386 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2387 IoDeleteDevice(DeviceObject
);
2388 return STATUS_NO_SUCH_DEVICE
;
2391 /* Bus FDO is initialized */
2392 RamdiskBusFdo
= DeviceObject
;
2394 /* Loop for loader block */
2397 /* Are we being booted from setup? Not yet supported */
2398 if (KeLoaderBlock
->SetupLdrBlock
)
2399 DPRINT1("FIXME: RamdiskAddDevice is UNSUPPORTED when being started from SETUPLDR!\n");
2400 // ASSERT(!KeLoaderBlock->SetupLdrBlock);
2404 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2405 Status
= STATUS_SUCCESS
;
2414 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2415 IN PUNICODE_STRING RegistryPath
)
2417 PCHAR BootDeviceName
, CommandLine
;
2418 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2420 DPRINT("RAM Disk Driver Initialized\n");
2422 /* Save the registry path */
2423 DriverRegistryPath
.MaximumLength
= RegistryPath
->Length
+ sizeof(UNICODE_NULL
);
2424 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2425 DriverRegistryPath
.MaximumLength
,
2427 if (!DriverRegistryPath
.Buffer
)
2429 return STATUS_INSUFFICIENT_RESOURCES
;
2431 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2433 /* Query ramdisk parameters */
2434 QueryParameters(&DriverRegistryPath
);
2436 /* Set device routines */
2437 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2438 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2439 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2440 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2441 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2442 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2443 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2444 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2445 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2446 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2447 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2448 DriverObject
->DriverUnload
= RamdiskUnload
;
2450 /* Check for a loader block */
2453 /* Get the boot device name */
2454 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2457 /* Check if we're booting from ramdisk */
2458 if ((strlen(BootDeviceName
) >= 10) &&
2459 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2461 /* We'll have to tell the PnP Manager */
2462 ReportDetectedDevice
= TRUE
;
2464 /* Check for a command line */
2465 CommandLine
= KeLoaderBlock
->LoadOptions
;
2468 /* Check if this is an ISO boot */
2469 if (strstr(CommandLine
, "RDEXPORTASCD"))
2471 /* Remember for later */
2472 ExportBootDiskAsCd
= TRUE
;
2475 /* Check if this is PE boot */
2476 if (strstr(CommandLine
, "MININT"))
2478 /* Remember for later */
2487 /* Installing from Ramdisk isn't supported yet */
2488 if (KeLoaderBlock
->SetupLdrBlock
)
2489 DPRINT1("FIXME: Installing from RamDisk is UNSUPPORTED!\n");
2490 // ASSERT(!KeLoaderBlock->SetupLdrBlock);
2492 /* Are we reporting the device */
2493 if (ReportDetectedDevice
)
2496 Status
= IoReportDetectedDevice(DriverObject
,
2497 InterfaceTypeUndefined
,
2503 &PhysicalDeviceObject
);
2504 if (NT_SUCCESS(Status
))
2506 /* Create the device object */
2507 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2508 if (NT_SUCCESS(Status
))
2511 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2512 Status
= STATUS_SUCCESS
;
2519 Status
= STATUS_SUCCESS
;