2 * PROJECT: Ramdisk Class Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/storage/class/ramdisk/ramdisk.c
5 * PURPOSE: Main Driver Routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
25 #include <reactos/drivers/ntddrdsk.h>
26 #include "../../../filesystems/fs_rec/fs_rec.h"
31 /* GLOBALS ********************************************************************/
33 #define RAMDISK_SESSION_SIZE \
34 FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
36 #define RAMDISK_TOC_SIZE \
37 FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
39 #define TOC_DATA_TRACK (0x04)
41 typedef enum _RAMDISK_DEVICE_TYPE
45 } RAMDISK_DEVICE_TYPE
;
47 typedef enum _RAMDISK_DEVICE_STATE
49 RamdiskStateUninitialized
,
54 RamdiskStateBusRemoved
,
55 RamdiskStateEnumerated
,
56 } RAMDISK_DEVICE_STATE
;
58 DEFINE_GUID(RamdiskBusInterface
,
62 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
64 typedef struct _RAMDISK_EXTENSION
66 RAMDISK_DEVICE_TYPE Type
;
67 RAMDISK_DEVICE_STATE State
;
68 PDEVICE_OBJECT DeviceObject
;
69 PDEVICE_OBJECT PhysicalDeviceObject
;
70 PDEVICE_OBJECT AttachedDevice
;
71 IO_REMOVE_LOCK RemoveLock
;
72 UNICODE_STRING DriveDeviceName
;
73 UNICODE_STRING BusDeviceName
;
74 FAST_MUTEX DiskListLock
;
76 } RAMDISK_EXTENSION
, *PRAMDISK_EXTENSION
;
78 typedef struct _RAMDISK_BUS_EXTENSION
81 } RAMDISK_BUS_EXTENSION
, *PRAMDISK_BUS_EXTENSION
;
83 typedef struct _RAMDISK_DRIVE_EXTENSION
86 // Inherited base class
91 // Data we get from the creator
94 UNICODE_STRING GuidString
;
95 UNICODE_STRING SymbolicLinkName
;
97 RAMDISK_CREATE_OPTIONS DiskOptions
;
98 LARGE_INTEGER DiskLength
;
104 // Data we get from the disk
106 ULONG BytesPerSector
;
107 ULONG SectorsPerTrack
;
111 } RAMDISK_DRIVE_EXTENSION
, *PRAMDISK_DRIVE_EXTENSION
;
113 ULONG MaximumViewLength
;
114 ULONG MaximumPerDiskViewLength
;
115 ULONG ReportDetectedDevice
;
116 ULONG MarkRamdisksAsRemovable
;
117 ULONG MinimumViewCount
;
118 ULONG DefaultViewCount
;
119 ULONG MaximumViewCount
;
120 ULONG MinimumViewLength
;
121 ULONG DefaultViewLength
;
122 UNICODE_STRING DriverRegistryPath
;
123 BOOLEAN ExportBootDiskAsCd
;
125 PDEVICE_OBJECT RamdiskBusFdo
;
127 /* FUNCTIONS ******************************************************************/
131 QueryParameters(IN PUNICODE_STRING RegistryPath
)
133 ULONG MinView
, DefView
, MinViewLength
, DefViewLength
, MaxViewLength
;
134 RTL_QUERY_REGISTRY_TABLE QueryTable
[10];
139 MaximumViewLength
= 0x10000000u
;
140 MaximumPerDiskViewLength
= 0x10000000u
;
141 ReportDetectedDevice
= 0;
142 MarkRamdisksAsRemovable
= 0;
143 MinimumViewCount
= 2;
144 DefaultViewCount
= 16;
145 MaximumViewCount
= 64;
146 MinimumViewLength
= 0x10000u
;
147 DefaultViewLength
= 0x100000u
;
150 // Setup the query table and query the registry
152 RtlZeroMemory(QueryTable
, sizeof(QueryTable
));
153 QueryTable
[0].Flags
= 1;
154 QueryTable
[0].Name
= L
"Parameters";
155 QueryTable
[1].Flags
= 32;
156 QueryTable
[1].Name
= L
"ReportDetectedDevice";
157 QueryTable
[1].EntryContext
= &ReportDetectedDevice
;
158 QueryTable
[2].Flags
= 32;
159 QueryTable
[2].Name
= L
"MarkRamdisksAsRemovable";
160 QueryTable
[2].EntryContext
= &MarkRamdisksAsRemovable
;
161 QueryTable
[3].Flags
= 32;
162 QueryTable
[3].Name
= L
"MinimumViewCount";
163 QueryTable
[3].EntryContext
= &MinimumViewCount
;
164 QueryTable
[4].Flags
= 32;
165 QueryTable
[4].Name
= L
"DefaultViewCount";
166 QueryTable
[4].EntryContext
= &DefaultViewCount
;
167 QueryTable
[5].Flags
= 32;
168 QueryTable
[5].Name
= L
"MaximumViewCount";
169 QueryTable
[5].EntryContext
= &MaximumViewCount
;
170 QueryTable
[6].Flags
= 32;
171 QueryTable
[6].Name
= L
"MinimumViewLength";
172 QueryTable
[6].EntryContext
= &MinimumViewLength
;
173 QueryTable
[7].Flags
= 32;
174 QueryTable
[7].Name
= L
"DefaultViewLength";
175 QueryTable
[7].EntryContext
= &DefaultViewLength
;
176 QueryTable
[8].Flags
= 32;
177 QueryTable
[8].Name
= L
"MaximumViewLength";
178 QueryTable
[8].EntryContext
= &MaximumViewLength
;
179 QueryTable
[9].Flags
= 32;
180 QueryTable
[9].Name
= L
"MaximumPerDiskViewLength";
181 QueryTable
[9].EntryContext
= &MaximumPerDiskViewLength
;
182 RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL
,
183 RegistryPath
->Buffer
,
189 // Parse minimum view count, cannot be bigger than 256 or smaller than 2
191 MinView
= MinimumViewCount
;
192 if (MinimumViewCount
>= 2)
194 if (MinimumViewCount
> 256) MinView
= 256;
200 MinimumViewCount
= MinView
;
203 // Parse default view count, cannot be bigger than 256 or smaller than minimum
205 DefView
= DefaultViewCount
;
206 if (DefaultViewCount
>= MinView
)
208 if (DefaultViewCount
> 256) DefView
= 256;
214 DefaultViewCount
= DefView
;
217 // Parse maximum view count, cannot be bigger than 256 or smaller than default
219 if (MaximumViewCount
>= DefView
)
221 if (MaximumViewCount
> 256) MaximumViewCount
= 256;
225 MaximumViewCount
= DefView
;
229 // Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
231 MinViewLength
= MinimumViewLength
;
232 if (MinimumViewLength
>= 0x10000)
234 if (MinimumViewLength
> 0x40000000) MinViewLength
= 0x40000000u
;
238 MinViewLength
= 0x10000u
;
240 MinimumViewLength
= MinViewLength
;
243 // Parse default view length, cannot be bigger than 1GB or smaller than minimum
245 DefViewLength
= DefaultViewLength
;
246 if (DefaultViewLength
>= MinViewLength
)
248 if (DefaultViewLength
> 0x40000000) DefViewLength
= 0x40000000u
;
252 DefViewLength
= MinViewLength
;
254 DefaultViewLength
= DefViewLength
;
257 // Parse maximum view length, cannot be bigger than 1GB or smaller than default
259 MaxViewLength
= MaximumViewLength
;
260 if (MaximumViewLength
>= DefViewLength
)
262 if (MaximumViewLength
> 0x40000000) MaxViewLength
= 0x40000000u
;
266 MaxViewLength
= DefViewLength
;
268 MaximumViewLength
= MaxViewLength
;
271 // Parse maximum view length per disk, cannot be smaller than 16MB
273 if (MaximumPerDiskViewLength
>= 0x1000000)
275 if (MaxViewLength
> 0xFFFFFFFF) MaximumPerDiskViewLength
= -1;
279 MaximumPerDiskViewLength
= 0x1000000u
;
285 RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
286 IN LARGE_INTEGER Offset
,
288 OUT PULONG OutputLength
)
290 PHYSICAL_ADDRESS PhysicalAddress
;
294 LARGE_INTEGER ActualOffset
;
295 LARGE_INTEGER ActualPages
;
298 // We only support boot disks for now
300 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
303 // Calculate the actual offset in the drive
305 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
310 ActualPages
.QuadPart
= ActualOffset
.QuadPart
>> PAGE_SHIFT
;
313 // Now add the base page
315 ActualPages
.QuadPart
= DeviceExtension
->BasePage
+ ActualPages
.QuadPart
;
318 // Calculate final amount of bytes
320 PhysicalAddress
.QuadPart
= ActualPages
.QuadPart
<< PAGE_SHIFT
;
323 // Calculate pages spanned for the mapping
325 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
328 // And convert this back to bytes
330 ActualLength
<<= PAGE_SHIFT
;
333 // Get the offset within the page
335 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
338 // Map the I/O Space from the loader
340 MappedBase
= MmMapIoSpace(PhysicalAddress
, ActualLength
, MmCached
);
343 // Return actual offset within the page as well as the length
345 if (MappedBase
) MappedBase
= (PVOID
)((ULONG_PTR
)MappedBase
+ PageOffset
);
346 *OutputLength
= Length
;
352 RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
,
353 IN PVOID BaseAddress
,
354 IN LARGE_INTEGER Offset
,
357 LARGE_INTEGER ActualOffset
;
362 // We only support boot disks for now
364 ASSERT(DeviceExtension
->DiskType
== RAMDISK_BOOT_DISK
);
367 // Calculate the actual offset in the drive
369 ActualOffset
.QuadPart
= DeviceExtension
->DiskOffset
+ Offset
.QuadPart
;
372 // Calculate pages spanned for the mapping
374 ActualLength
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset
.QuadPart
, Length
);
377 // And convert this back to bytes
379 ActualLength
<<= PAGE_SHIFT
;
382 // Get the offset within the page
384 PageOffset
= BYTE_OFFSET(ActualOffset
.QuadPart
);
387 // Calculate actual base address where we mapped this
389 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
- PageOffset
);
392 // Unmap the I/O space we got from the loader
394 MmUnmapIoSpace(BaseAddress
, ActualLength
);
399 RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension
,
400 IN PRAMDISK_CREATE_INPUT Input
,
401 IN BOOLEAN ValidateOnly
,
402 OUT PRAMDISK_DRIVE_EXTENSION
*NewDriveExtension
)
404 ULONG BasePage
, ViewCount
, DiskType
, Length
;
406 PDEVICE_OBJECT DeviceObject
;
407 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
409 WCHAR LocalBuffer
[16];
410 UNICODE_STRING SymbolicLinkName
, DriveString
, GuidString
, DeviceName
;
411 PPACKED_BOOT_SECTOR BootSector
;
412 BIOS_PARAMETER_BLOCK BiosBlock
;
413 ULONG BytesPerSector
, SectorsPerTrack
, Heads
, BytesRead
;
415 LARGE_INTEGER CurrentOffset
, CylinderSize
, DiskLength
;
416 ULONG CylinderCount
, SizeByCylinders
;
419 // Check if we're a boot RAM disk
421 DiskType
= Input
->DiskType
;
422 if (DiskType
>= RAMDISK_BOOT_DISK
)
425 // Check if we're an ISO
427 if (DiskType
== RAMDISK_BOOT_DISK
)
430 // NTLDR mounted us somewhere
432 BasePage
= Input
->BasePage
;
433 if (!BasePage
) return STATUS_INVALID_PARAMETER
;
436 // Sanitize disk options
438 Input
->Options
.Fixed
= TRUE
;
439 Input
->Options
.Readonly
= Input
->Options
.ExportAsCd
|
440 Input
->Options
.Readonly
;
441 Input
->Options
.Hidden
= FALSE
;
442 Input
->Options
.NoDosDevice
= FALSE
;
443 Input
->Options
.NoDriveLetter
= IsWinPEBoot
? TRUE
: FALSE
;
448 // The only other possibility is a WIM disk
450 if (DiskType
!= RAMDISK_WIM_DISK
)
455 return STATUS_INVALID_PARAMETER
;
459 // Read the view count instead
461 ViewCount
= Input
->ViewCount
;
464 // Sanitize disk options
466 Input
->Options
.Hidden
= FALSE
;
467 Input
->Options
.NoDosDevice
= FALSE
;
468 Input
->Options
.Readonly
= FALSE
;
469 Input
->Options
.NoDriveLetter
= TRUE
;
470 Input
->Options
.Fixed
= TRUE
;
474 // Are we just validating and returning to the user?
476 if (ValidateOnly
) return STATUS_SUCCESS
;
479 // Build the GUID string
481 Status
= RtlStringFromGUID(&Input
->DiskGuid
, &GuidString
);
482 if (!(NT_SUCCESS(Status
)) || !(GuidString
.Buffer
))
487 Status
= STATUS_INSUFFICIENT_RESOURCES
;
492 // Allocate our device name
494 Length
= GuidString
.Length
+ 32;
495 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
503 Status
= STATUS_INSUFFICIENT_RESOURCES
;
508 // Build the device name string
510 DeviceName
.Buffer
= Buffer
;
511 DeviceName
.Length
= Length
- 2;
512 DeviceName
.MaximumLength
= Length
;
513 wcsncpy(Buffer
, L
"\\Device\\Ramdisk", Length
/ sizeof(WCHAR
));
514 wcsncat(Buffer
, GuidString
.Buffer
, Length
/ sizeof(WCHAR
));
517 // Create the drive device
519 Status
= IoCreateDevice(DeviceExtension
->DeviceObject
->DriverObject
,
520 sizeof(RAMDISK_DRIVE_EXTENSION
),
522 (Input
->Options
.ExportAsCd
) ?
523 FILE_DEVICE_CD_ROM
: FILE_DEVICE_DISK
,
527 if (!NT_SUCCESS(Status
)) goto FailCreate
;
530 // Grab the drive extension
532 DriveExtension
= DeviceObject
->DeviceExtension
;
535 // Check if we need a DOS device
537 if (!Input
->Options
.NoDosDevice
)
540 // Build the symbolic link name
542 SymbolicLinkName
.MaximumLength
= GuidString
.Length
+ 36;
543 SymbolicLinkName
.Length
= GuidString
.Length
+ 34;
544 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
545 SymbolicLinkName
.MaximumLength
,
547 SymbolicLinkName
.Buffer
= Buffer
;
554 L
"\\GLOBAL??\\Ramdisk",
555 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
558 SymbolicLinkName
.MaximumLength
/ sizeof(WCHAR
));
559 Status
= IoCreateSymbolicLink(&SymbolicLinkName
, &DeviceName
);
560 if (!NT_SUCCESS(Status
))
565 Input
->Options
.NoDosDevice
= TRUE
;
567 SymbolicLinkName
.Buffer
= NULL
;
575 Input
->Options
.NoDosDevice
= TRUE
;
579 // It this an ISO boot ramdisk?
581 if (Input
->DiskType
== RAMDISK_BOOT_DISK
)
584 // Does it need a drive letter?
586 if (!Input
->Options
.NoDriveLetter
)
589 // Build it and take over the existing symbolic link
591 _snwprintf(LocalBuffer
,
593 L
"\\DosDevices\\%wc:",
595 RtlInitUnicodeString(&DriveString
, LocalBuffer
);
596 IoDeleteSymbolicLink(&DriveString
);
597 IoCreateSymbolicLink(&DriveString
, &DeviceName
);
600 // Save the drive letter
602 DriveExtension
->DriveLetter
= Input
->DriveLetter
;
609 // Setup the device object flags
611 DeviceObject
->Flags
|= (DO_XIP
| DO_POWER_PAGABLE
| DO_DIRECT_IO
);
612 DeviceObject
->AlignmentRequirement
= 1;
615 // Build the drive FDO
617 *NewDriveExtension
= DriveExtension
;
618 DriveExtension
->Type
= RamdiskDrive
;
619 DiskLength
= Input
->DiskLength
;
620 ExInitializeFastMutex(&DriveExtension
->DiskListLock
);
621 IoInitializeRemoveLock(&DriveExtension
->RemoveLock
,
625 DriveExtension
->DriveDeviceName
= DeviceName
;
626 DriveExtension
->SymbolicLinkName
= SymbolicLinkName
;
627 DriveExtension
->GuidString
= GuidString
;
628 DriveExtension
->DiskGuid
= Input
->DiskGuid
;
629 DriveExtension
->PhysicalDeviceObject
= DeviceObject
;
630 DriveExtension
->DeviceObject
= RamdiskBusFdo
;
631 DriveExtension
->AttachedDevice
= RamdiskBusFdo
;
632 DriveExtension
->DiskType
= Input
->DiskType
;
633 DriveExtension
->DiskOptions
= Input
->Options
;
634 DriveExtension
->DiskLength
= DiskLength
;
635 DriveExtension
->DiskOffset
= Input
->DiskOffset
;
636 DriveExtension
->BasePage
= Input
->BasePage
;
637 DriveExtension
->BytesPerSector
= 0;
638 DriveExtension
->SectorsPerTrack
= 0;
639 DriveExtension
->NumberOfHeads
= 0;
642 // Make sure we don't free it later
644 DeviceName
.Buffer
= NULL
;
645 SymbolicLinkName
.Buffer
= NULL
;
646 GuidString
.Buffer
= NULL
;
649 // Check if this is an boot disk, or a registry ram drive
651 if (!(Input
->Options
.ExportAsCd
) &&
652 (Input
->DiskType
== RAMDISK_BOOT_DISK
))
655 // Not an ISO boot, but it's a boot FS -- map it to figure out the
658 CurrentOffset
.QuadPart
= 0;
659 BaseAddress
= RamdiskMapPages(DriveExtension
,
668 BootSector
= (PPACKED_BOOT_SECTOR
)BaseAddress
;
669 FatUnpackBios(&BiosBlock
, &BootSector
->PackedBpb
);
670 BytesPerSector
= BiosBlock
.BytesPerSector
;
671 SectorsPerTrack
= BiosBlock
.SectorsPerTrack
;
672 Heads
= BiosBlock
.Heads
;
677 DriveExtension
->BytesPerSector
= BytesPerSector
;
678 DriveExtension
->SectorsPerTrack
= SectorsPerTrack
;
679 DriveExtension
->NumberOfHeads
= Heads
;
684 CurrentOffset
.QuadPart
= 0;
685 RamdiskUnmapPages(DriveExtension
,
695 Status
= STATUS_INSUFFICIENT_RESOURCES
;
701 // Check if the drive settings haven't been set yet
703 if ((DriveExtension
->BytesPerSector
== 0) ||
704 (DriveExtension
->SectorsPerTrack
== 0) ||
705 (DriveExtension
->NumberOfHeads
== 0))
708 // Check if this is a CD
710 if (Input
->Options
.ExportAsCd
)
713 // Setup partition parameters default for ISO 9660
715 DriveExtension
->BytesPerSector
= 2048;
716 DriveExtension
->SectorsPerTrack
= 32;
717 DriveExtension
->NumberOfHeads
= 64;
722 // Setup partition parameters default for FAT
724 DriveExtension
->BytesPerSector
= 512;
725 DriveExtension
->SectorsPerTrack
= 128;
726 DriveExtension
->NumberOfHeads
= 16;
731 // Calculate the cylinder size
733 CylinderSize
.QuadPart
= DriveExtension
->BytesPerSector
*
734 DriveExtension
->SectorsPerTrack
*
735 DriveExtension
->NumberOfHeads
;
736 CylinderCount
= DiskLength
.QuadPart
/ CylinderSize
.QuadPart
;
737 SizeByCylinders
= CylinderSize
.QuadPart
* CylinderCount
;
738 DriveExtension
->Cylinders
= CylinderCount
;
739 if ((DiskLength
.HighPart
> 0) || (SizeByCylinders
< DiskLength
.LowPart
))
742 // Align cylinder size up
744 DriveExtension
->Cylinders
++;
748 // Acquire the disk lock
750 KeEnterCriticalRegion();
751 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
756 InsertTailList(&DeviceExtension
->DiskList
, &DriveExtension
->DiskList
);
761 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
762 KeLeaveCriticalRegion();
767 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
768 return STATUS_SUCCESS
;
774 return STATUS_SUCCESS
;
779 RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject
,
781 IN BOOLEAN ValidateOnly
)
783 PRAMDISK_CREATE_INPUT Input
;
785 PRAMDISK_BUS_EXTENSION DeviceExtension
;
786 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
788 PWCHAR FileNameStart
, FileNameEnd
;
790 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
793 // Get the device extension and our input data
795 DeviceExtension
= DeviceObject
->DeviceExtension
;
796 Length
= IoStackLocation
->Parameters
.DeviceIoControl
.InputBufferLength
;
797 Input
= (PRAMDISK_CREATE_INPUT
)Irp
->AssociatedIrp
.SystemBuffer
;
800 // Validate input parameters
802 if ((Length
< sizeof(RAMDISK_CREATE_INPUT
)) ||
803 (Input
->Version
!= sizeof(RAMDISK_CREATE_INPUT
)))
808 return STATUS_INVALID_PARAMETER
;
812 // Validate the disk type
814 DiskType
= Input
->DiskType
;
815 if (DiskType
== RAMDISK_WIM_DISK
) return STATUS_INVALID_PARAMETER
;
818 // Look at the disk type
820 if (DiskType
== RAMDISK_BOOT_DISK
)
823 // We only allow this as an early-init boot
825 if (!KeLoaderBlock
) return STATUS_INVALID_PARAMETER
;
828 // Save command-line flags
830 if (ExportBootDiskAsCd
) Input
->Options
.ExportAsCd
= TRUE
;
831 if (IsWinPEBoot
) Input
->Options
.NoDriveLetter
= TRUE
;
835 // Validate the disk type
837 if ((Input
->Options
.ExportAsCd
) && (DiskType
!= RAMDISK_BOOT_DISK
))
840 // If the type isn't CDFS, it has to at least be raw CD
842 if (DiskType
!= RAMDISK_MEMORY_MAPPED_DISK
) return STATUS_INVALID_PARAMETER
;
846 // Check if this is an actual file
848 if (DiskType
<= RAMDISK_MEMORY_MAPPED_DISK
)
851 // Validate the file name
853 FileNameStart
= (PWCHAR
)((ULONG_PTR
)Input
+ Length
);
854 FileNameEnd
= Input
->FileName
+ 1;
855 while ((FileNameEnd
< FileNameStart
) && *(FileNameEnd
)) FileNameEnd
++;
856 if (FileNameEnd
== FileNameStart
) return STATUS_INVALID_PARAMETER
;
860 // Create the actual device
862 Status
= RamdiskCreateDiskDevice(DeviceExtension
,
866 if (NT_SUCCESS(Status
))
869 // Invalidate and set success
871 IoInvalidateDeviceRelations(DeviceExtension
->PhysicalDeviceObject
, 0);
872 Irp
->IoStatus
.Information
= STATUS_SUCCESS
;
883 RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject
,
886 PRAMDISK_BUS_EXTENSION DeviceExtension
;
888 PIO_STACK_LOCATION IoStackLocation
;
892 // Get the stack location
894 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
897 // Free the work item
899 IoFreeWorkItem(Irp
->Tail
.Overlay
.DriverContext
[0]);
902 // Grab the device extension and lock it
904 DeviceExtension
= DeviceObject
->DeviceExtension
;
905 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
906 if (NT_SUCCESS(Status
))
909 // Discriminate by major code
911 switch (IoStackLocation
->MajorFunction
)
916 case IRP_MJ_DEVICE_CONTROL
:
919 // Let's take a look at the IOCTL
921 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
924 // Ramdisk create request
926 case FSCTL_CREATE_RAM_DISK
:
929 // This time we'll do it for real
931 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, FALSE
);
934 case IOCTL_DISK_SET_PARTITION_INFO
:
936 DPRINT1("Set partition info request\n");
941 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
943 DPRINT1("Get drive layout request\n");
948 case IOCTL_DISK_GET_PARTITION_INFO
:
950 DPRINT1("Get partitinon info request\n");
957 DPRINT1("Invalid request\n");
969 // Read or write request
974 DPRINT1("Read/Write request\n");
980 // Internal request (SCSI?)
982 case IRP_MJ_INTERNAL_DEVICE_CONTROL
:
984 DPRINT1("SCSI request\n");
992 case IRP_MJ_FLUSH_BUFFERS
:
994 DPRINT1("Flush request\n");
1004 DPRINT1("Invalid request: %lx\n", IoStackLocation
->MajorFunction
);
1013 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1014 Irp
->IoStatus
.Status
= Status
;
1015 Irp
->IoStatus
.Information
= 0;
1016 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1023 Irp
->IoStatus
.Status
= Status
;
1024 Irp
->IoStatus
.Information
= 0;
1025 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1030 SendIrpToThread(IN PDEVICE_OBJECT DeviceObject
,
1033 PIO_WORKITEM WorkItem
;
1036 // Mark the IRP pending
1038 IoMarkIrpPending(Irp
);
1041 // Allocate a work item
1043 WorkItem
= IoAllocateWorkItem(DeviceObject
);
1049 Irp
->Tail
.Overlay
.DriverContext
[0] = WorkItem
;
1050 IoQueueWorkItem(WorkItem
, RamdiskWorkerThread
, DelayedWorkQueue
, Irp
);
1051 return STATUS_PENDING
;
1058 return STATUS_INSUFFICIENT_RESOURCES
;
1064 RamdiskReadWriteReal(IN PIRP Irp
,
1065 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1068 PVOID CurrentBase
, SystemVa
, BaseAddress
;
1069 PIO_STACK_LOCATION IoStackLocation
;
1070 LARGE_INTEGER CurrentOffset
;
1071 ULONG BytesRead
, BytesLeft
, CopyLength
;
1072 PVOID Source
, Destination
;
1076 // Get the MDL and check if it's mapped
1078 Mdl
= Irp
->MdlAddress
;
1079 if (Mdl
->MdlFlags
& (MDL_MAPPED_TO_SYSTEM_VA
| MDL_SOURCE_IS_NONPAGED_POOL
))
1082 // Use the mapped address
1084 SystemVa
= Mdl
->MappedSystemVa
;
1091 SystemVa
= MmMapLockedPagesSpecifyCache(Mdl
,
1096 NormalPagePriority
);
1100 // Make sure we were able to map it
1102 CurrentBase
= SystemVa
;
1103 if (!SystemVa
) return STATUS_INSUFFICIENT_RESOURCES
;
1106 // Initialize default
1108 Irp
->IoStatus
.Information
= 0;
1111 // Get the I/O Stack Location and capture the data
1113 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1114 CurrentOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1115 BytesLeft
= IoStackLocation
->Parameters
.Read
.Length
;
1116 if (!BytesLeft
) return STATUS_INVALID_PARAMETER
;
1126 BaseAddress
= RamdiskMapPages(DeviceExtension
,
1130 if (!BaseAddress
) return STATUS_INSUFFICIENT_RESOURCES
;
1133 // Update our lengths
1135 Irp
->IoStatus
.Information
+= BytesRead
;
1136 CopyLength
= BytesRead
;
1139 // Check if this was a read or write
1141 Status
= STATUS_SUCCESS
;
1142 if (IoStackLocation
->MajorFunction
== IRP_MJ_READ
)
1145 // Set our copy parameters
1147 Destination
= CurrentBase
;
1148 Source
= BaseAddress
;
1151 else if (IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
)
1154 // Set our copy parameters
1156 Destination
= BaseAddress
;
1157 Source
= CurrentBase
;
1162 RtlCopyMemory(Destination
, Source
, CopyLength
);
1167 // Prepare us for failure
1169 BytesLeft
= CopyLength
;
1170 Status
= STATUS_INVALID_PARAMETER
;
1176 RamdiskUnmapPages(DeviceExtension
,
1182 // Update offset and bytes left
1184 BytesLeft
-= BytesRead
;
1185 CurrentOffset
.QuadPart
+= BytesRead
;
1186 CurrentBase
= (PVOID
)((ULONG_PTR
)CurrentBase
+ BytesRead
);
1189 // Check if we're done
1191 if (!BytesLeft
) return Status
;
1197 RamdiskGetPartitionInfo(IN PIRP Irp
,
1198 IN PRAMDISK_DRIVE_EXTENSION DeviceExtension
)
1201 PPARTITION_INFORMATION PartitionInfo
;
1203 LARGE_INTEGER Zero
= {{0, 0}};
1205 PIO_STACK_LOCATION IoStackLocation
;
1208 // Validate the length
1210 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1211 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1212 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1217 Status
= STATUS_BUFFER_TOO_SMALL
;
1218 Irp
->IoStatus
.Status
= Status
;
1219 Irp
->IoStatus
.Information
= 0;
1224 // Map the partition table
1226 BaseAddress
= RamdiskMapPages(DeviceExtension
, Zero
, PAGE_SIZE
, &Length
);
1232 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1233 Irp
->IoStatus
.Status
= Status
;
1234 Irp
->IoStatus
.Information
= 0;
1239 // Fill out the information
1241 PartitionInfo
= Irp
->AssociatedIrp
.SystemBuffer
;
1242 PartitionInfo
->StartingOffset
.QuadPart
= DeviceExtension
->BytesPerSector
;
1243 PartitionInfo
->PartitionLength
.QuadPart
= DeviceExtension
->BytesPerSector
*
1244 DeviceExtension
->SectorsPerTrack
*
1245 DeviceExtension
->NumberOfHeads
*
1246 DeviceExtension
->Cylinders
;
1247 PartitionInfo
->HiddenSectors
= DeviceExtension
->HiddenSectors
;
1248 PartitionInfo
->PartitionNumber
= 0;
1249 PartitionInfo
->PartitionType
= PARTITION_FAT32
; //*((PCHAR)BaseAddress + 450);
1250 PartitionInfo
->BootIndicator
= (DeviceExtension
->DiskType
==
1251 RAMDISK_BOOT_DISK
) ? TRUE
: FALSE
;
1252 PartitionInfo
->RecognizedPartition
= IsRecognizedPartition(PartitionInfo
->
1254 PartitionInfo
->RewritePartition
= FALSE
;
1257 // Unmap the partition table
1259 RamdiskUnmapPages(DeviceExtension
, BaseAddress
, Zero
, Length
);
1264 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1265 Irp
->IoStatus
.Information
= sizeof(PARTITION_INFORMATION
);
1266 return STATUS_SUCCESS
;
1271 RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject
,
1277 Irp
->IoStatus
.Information
= 1;
1278 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1279 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1280 return STATUS_SUCCESS
;
1285 RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject
,
1288 PRAMDISK_DRIVE_EXTENSION DeviceExtension
;
1290 LARGE_INTEGER ByteOffset
;
1291 PIO_STACK_LOCATION IoStackLocation
;
1292 NTSTATUS Status
, ReturnStatus
;
1295 // Get the device extension and make sure this isn't a bus
1297 DeviceExtension
= DeviceObject
->DeviceExtension
;
1298 if (DeviceExtension
->Type
== RamdiskBus
)
1303 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1308 // Capture parameters
1310 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1311 Length
= IoStackLocation
->Parameters
.Read
.Length
;
1312 ByteOffset
= IoStackLocation
->Parameters
.Read
.ByteOffset
;
1315 // FIXME: Validate offset
1319 // FIXME: Validate sector
1325 if ((IoStackLocation
->MajorFunction
== IRP_MJ_WRITE
) &&
1326 (DeviceExtension
->DiskOptions
.Readonly
))
1329 // Fail, this is read-only
1331 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
1336 // See if we want to do this sync or async
1338 if (DeviceExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1343 Status
= RamdiskReadWriteReal(Irp
, DeviceExtension
);
1348 // Queue it to the worker
1350 Status
= SendIrpToThread(DeviceObject
, Irp
);
1351 ReturnStatus
= STATUS_PENDING
;
1354 // Check if we're pending or not
1356 if (Status
!= STATUS_PENDING
)
1362 Irp
->IoStatus
.Status
= Status
;
1363 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
1364 ReturnStatus
= Status
;
1370 return ReturnStatus
;
1375 RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject
,
1379 PIO_STACK_LOCATION IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1380 PRAMDISK_BUS_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
1381 PRAMDISK_DRIVE_EXTENSION DriveExtension
= (PVOID
)DeviceExtension
;
1384 PDISK_GEOMETRY DiskGeometry
;
1387 // Grab the remove lock
1389 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1390 if (!NT_SUCCESS(Status
))
1395 Irp
->IoStatus
.Information
= 0;
1396 Irp
->IoStatus
.Status
= Status
;
1397 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1402 // Setup some defaults
1404 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1408 // Check if this is an bus device or the drive
1410 if (DeviceExtension
->Type
== RamdiskBus
)
1413 // Check what the request is
1415 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1418 // Request to create a ramdisk
1420 case FSCTL_CREATE_RAM_DISK
:
1425 Status
= RamdiskCreateRamdisk(DeviceObject
, Irp
, TRUE
);
1426 if (!NT_SUCCESS(Status
)) goto CompleteRequest
;
1432 // We don't handle anything else yet
1441 // Check what the request is
1443 switch (IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
)
1445 case IOCTL_DISK_CHECK_VERIFY
:
1446 case IOCTL_STORAGE_CHECK_VERIFY
:
1447 case IOCTL_STORAGE_CHECK_VERIFY2
:
1448 case IOCTL_CDROM_CHECK_VERIFY
:
1454 case IOCTL_STORAGE_GET_MEDIA_TYPES
:
1455 case IOCTL_DISK_GET_MEDIA_TYPES
:
1456 case IOCTL_DISK_GET_DRIVE_GEOMETRY
:
1457 case IOCTL_CDROM_GET_DRIVE_GEOMETRY
:
1460 // Validate the length
1462 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1463 OutputBufferLength
< sizeof(DISK_GEOMETRY
))
1468 Status
= STATUS_BUFFER_TOO_SMALL
;
1475 DiskGeometry
= Irp
->AssociatedIrp
.SystemBuffer
;
1476 DiskGeometry
->Cylinders
.QuadPart
= DriveExtension
->Cylinders
;
1477 DiskGeometry
->BytesPerSector
= DriveExtension
->BytesPerSector
;
1478 DiskGeometry
->SectorsPerTrack
= DriveExtension
->SectorsPerTrack
;
1479 DiskGeometry
->TracksPerCylinder
= DriveExtension
->NumberOfHeads
;
1480 DiskGeometry
->MediaType
= DriveExtension
->DiskOptions
.Fixed
?
1481 FixedMedia
: RemovableMedia
;
1486 Status
= STATUS_SUCCESS
;
1487 Information
= sizeof(DISK_GEOMETRY
);
1491 // Hack to support ReactOS's broken CDFS
1493 case IOCTL_CDROM_GET_LAST_SESSION
:
1496 // Validate the length
1498 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1499 OutputBufferLength
< RAMDISK_SESSION_SIZE
)
1504 Status
= STATUS_BUFFER_TOO_SMALL
;
1511 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1513 Toc
->Length
[1] = RAMDISK_SESSION_SIZE
- sizeof(Toc
->Length
);
1514 Toc
->FirstTrack
= 1;
1516 Toc
->TrackData
[0].Adr
= 1;
1517 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1518 Toc
->TrackData
[0].TrackNumber
= 1;
1519 Toc
->TrackData
[0].Address
[0] =
1520 Toc
->TrackData
[0].Address
[1] =
1521 Toc
->TrackData
[0].Address
[2] =
1522 Toc
->TrackData
[0].Address
[3] = 0;
1527 Status
= STATUS_SUCCESS
;
1528 Information
= RAMDISK_SESSION_SIZE
;
1531 case IOCTL_CDROM_READ_TOC
:
1534 // Validate the length
1536 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1537 OutputBufferLength
< sizeof(CDROM_TOC
))
1542 Status
= STATUS_BUFFER_TOO_SMALL
;
1549 Toc
= Irp
->AssociatedIrp
.SystemBuffer
;
1550 RtlZeroMemory(Toc
, sizeof(CDROM_TOC
));
1556 Toc
->Length
[1] = RAMDISK_TOC_SIZE
- sizeof(Toc
->Length
);
1557 Toc
->FirstTrack
= 1;
1559 Toc
->TrackData
[0].Adr
= 1;
1560 Toc
->TrackData
[0].Control
= TOC_DATA_TRACK
;
1561 Toc
->TrackData
[0].TrackNumber
= 1;
1566 Status
= STATUS_SUCCESS
;
1567 Information
= RAMDISK_TOC_SIZE
;
1570 case IOCTL_DISK_SET_PARTITION_INFO
:
1576 case IOCTL_DISK_GET_PARTITION_INFO
:
1579 // Validate the length
1581 if (IoStackLocation
->Parameters
.DeviceIoControl
.
1582 OutputBufferLength
< sizeof(PARTITION_INFORMATION
))
1587 Status
= STATUS_BUFFER_TOO_SMALL
;
1592 // Check if we need to do this sync or async
1594 if (DriveExtension
->DiskType
> RAMDISK_MEMORY_MAPPED_DISK
)
1597 // Call the helper function
1599 Status
= RamdiskGetPartitionInfo(Irp
, DriveExtension
);
1604 // Do it asynchronously later
1612 Information
= Irp
->IoStatus
.Information
;
1615 case IOCTL_DISK_GET_DRIVE_LAYOUT
:
1621 case IOCTL_DISK_GET_LENGTH_INFO
:
1627 case IOCTL_DISK_IS_WRITABLE
:
1633 case IOCTL_SCSI_MINIPORT
:
1639 case IOCTL_STORAGE_QUERY_PROPERTY
:
1645 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
:
1651 case IOCTL_MOUNTDEV_QUERY_STABLE_GUID
:
1657 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
:
1663 case IOCTL_VOLUME_SET_GPT_ATTRIBUTES
:
1669 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES
:
1675 case IOCTL_VOLUME_OFFLINE
:
1684 // Drive code not emulated
1686 DPRINT1("IOCTL: %lx\n", IoStackLocation
->Parameters
.DeviceIoControl
.IoControlCode
);
1691 // If requests drop down here, we just return them complete them
1693 goto CompleteRequest
;
1697 // Queue the request to our worker thread
1700 Status
= SendIrpToThread(DeviceObject
, Irp
);
1706 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1707 if (Status
!= STATUS_PENDING
)
1710 // Complete the request
1712 Irp
->IoStatus
.Status
= Status
;
1713 Irp
->IoStatus
.Information
= Information
;
1714 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1725 RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type
,
1726 IN PDEVICE_OBJECT DeviceObject
,
1729 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1730 PRAMDISK_DRIVE_EXTENSION DriveExtension
;
1731 PDEVICE_RELATIONS DeviceRelations
, OurDeviceRelations
;
1732 ULONG Count
, DiskCount
, FinalCount
;
1733 PLIST_ENTRY ListHead
, NextEntry
;
1734 PDEVICE_OBJECT
* DriveDeviceObject
;
1735 RAMDISK_DEVICE_STATE State
;
1738 // Get the device extension and check if this is a drive
1740 DeviceExtension
= DeviceObject
->DeviceExtension
;
1741 if (DeviceExtension
->Type
== RamdiskDrive
)
1751 // Anything but bus relations, we don't handle
1753 if (Type
) goto PassToNext
;
1756 // Acquire the disk list lock
1758 KeEnterCriticalRegion();
1759 ExAcquireFastMutex(&DeviceExtension
->DiskListLock
);
1762 // Did a device already fill relations?
1764 DeviceRelations
= (PDEVICE_RELATIONS
)Irp
->IoStatus
.Information
;
1765 if (DeviceRelations
)
1770 Count
= DeviceRelations
->Count
;
1781 // Now loop our drives
1784 ListHead
= &DeviceExtension
->DiskList
;
1785 NextEntry
= ListHead
->Flink
;
1786 while (NextEntry
!= ListHead
)
1789 // As long as it wasn't removed, count it in
1791 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1792 RAMDISK_DRIVE_EXTENSION
,
1794 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1797 // Move to the next one
1799 NextEntry
= NextEntry
->Flink
;
1803 // Now we know our final count
1805 FinalCount
= Count
+ DiskCount
;
1808 // Allocate the structure
1810 OurDeviceRelations
= ExAllocatePoolWithTag(PagedPool
,
1811 FIELD_OFFSET(DEVICE_RELATIONS
,
1814 sizeof(PDEVICE_OBJECT
),
1816 if (!OurDeviceRelations
)
1821 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1822 KeLeaveCriticalRegion();
1823 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
1824 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1825 return STATUS_INSUFFICIENT_RESOURCES
;
1829 // Check if we already had some relations
1836 RtlCopyMemory(OurDeviceRelations
->Objects
,
1837 DeviceRelations
->Objects
,
1838 Count
* sizeof(PDEVICE_OBJECT
));
1844 OurDeviceRelations
->Count
= FinalCount
;
1847 // Now loop our drives again
1849 ListHead
= &DeviceExtension
->DiskList
;
1850 NextEntry
= ListHead
->Flink
;
1851 while (NextEntry
!= ListHead
)
1854 // Go to the end of the list
1856 DriveDeviceObject
= &OurDeviceRelations
->Objects
[Count
];
1859 // Get the drive state
1861 DriveExtension
= CONTAINING_RECORD(NextEntry
,
1862 RAMDISK_DRIVE_EXTENSION
,
1864 State
= DriveExtension
->State
;
1867 // If it was removed or enumerated, we don't touch the device object
1869 if (State
>= RamdiskStateBusRemoved
)
1872 // If it was removed, we still have to keep track of this though
1874 if (State
== RamdiskStateBusRemoved
)
1877 // Mark it as enumerated now, but don't actually reference it
1879 DriveExtension
->State
= RamdiskStateEnumerated
;
1885 // First time it's enumerated, reference the device object
1887 ObReferenceObject(DriveExtension
->DeviceObject
);
1890 // Save the object pointer, and move on
1892 *DriveDeviceObject
++ = DriveExtension
->DeviceObject
;
1895 if (DriveExtension
->State
< RamdiskStateBusRemoved
) DiskCount
++;
1898 // Move to the next one
1900 NextEntry
= NextEntry
->Flink
;
1906 ExReleaseFastMutex(&DeviceExtension
->DiskListLock
);
1907 KeLeaveCriticalRegion();
1910 // Cleanup old relations
1912 if (DeviceRelations
) ExFreePool(DeviceRelations
);
1917 Irp
->IoStatus
.Information
= (ULONG_PTR
)OurDeviceRelations
;
1918 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1921 // Pass to the next driver
1924 IoCopyCurrentIrpStackLocationToNext(Irp
);
1925 return IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
1930 RamdiskPnp(IN PDEVICE_OBJECT DeviceObject
,
1933 PIO_STACK_LOCATION IoStackLocation
;
1934 PRAMDISK_BUS_EXTENSION DeviceExtension
;
1939 // Get the device extension and stack location
1941 DeviceExtension
= DeviceObject
->DeviceExtension
;
1942 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1943 Minor
= IoStackLocation
->MinorFunction
;
1946 // Check if the bus is removed
1948 if (DeviceExtension
->State
== RamdiskStateBusRemoved
)
1951 // Only remove-device and query-id are allowed
1953 if ((Minor
!= IRP_MN_REMOVE_DEVICE
) || (Minor
!= IRP_MN_QUERY_ID
))
1956 // Fail anything else
1958 Status
= STATUS_NO_SUCH_DEVICE
;
1959 Irp
->IoStatus
.Status
= Status
;
1960 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1966 // Acquire the remove lock
1968 Status
= IoAcquireRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
1969 if (!NT_SUCCESS(Status
))
1974 Irp
->IoStatus
.Information
= 0;
1975 Irp
->IoStatus
.Status
= Status
;
1976 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1981 // Query the IRP type
1985 case IRP_MN_START_DEVICE
:
1987 DPRINT1("PnP IRP: %lx\n", Minor
);
1991 case IRP_MN_QUERY_STOP_DEVICE
:
1993 DPRINT1("PnP IRP: %lx\n", Minor
);
1997 case IRP_MN_CANCEL_STOP_DEVICE
:
1999 DPRINT1("PnP IRP: %lx\n", Minor
);
2003 case IRP_MN_STOP_DEVICE
:
2005 DPRINT1("PnP IRP: %lx\n", Minor
);
2009 case IRP_MN_QUERY_REMOVE_DEVICE
:
2011 DPRINT1("PnP IRP: %lx\n", Minor
);
2015 case IRP_MN_CANCEL_REMOVE_DEVICE
:
2017 DPRINT1("PnP IRP: %lx\n", Minor
);
2021 case IRP_MN_REMOVE_DEVICE
:
2023 DPRINT1("PnP IRP: %lx\n", Minor
);
2027 case IRP_MN_SURPRISE_REMOVAL
:
2029 DPRINT1("PnP IRP: %lx\n", Minor
);
2033 case IRP_MN_QUERY_ID
:
2038 if (DeviceExtension
->Type
== RamdiskDrive
)
2040 DPRINT1("PnP IRP: %lx\n", Minor
);
2045 case IRP_MN_QUERY_BUS_INFORMATION
:
2050 if (DeviceExtension
->Type
== RamdiskDrive
)
2052 DPRINT1("PnP IRP: %lx\n", Minor
);
2059 DPRINT1("PnP IRP: %lx\n", Minor
);
2063 case IRP_MN_QUERY_DEVICE_TEXT
:
2068 if (DeviceExtension
->Type
== RamdiskDrive
)
2070 DPRINT1("PnP IRP: %lx\n", Minor
);
2075 case IRP_MN_QUERY_DEVICE_RELATIONS
:
2078 // Call our main routine
2080 Status
= RamdiskQueryDeviceRelations(IoStackLocation
->
2082 QueryDeviceRelations
.Type
,
2085 goto ReleaseAndReturn
;
2087 case IRP_MN_QUERY_CAPABILITIES
:
2092 if (DeviceExtension
->Type
== RamdiskDrive
)
2094 DPRINT1("PnP IRP: %lx\n", Minor
);
2099 case IRP_MN_QUERY_RESOURCES
:
2100 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS
:
2103 // Complete immediately without touching it
2105 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
2106 goto ReleaseAndReturn
;
2110 DPRINT1("Illegal IRP: %lx\n", Minor
);
2117 if (DeviceExtension
->Type
== RamdiskBus
)
2120 // Do we have an attached device?
2122 if (DeviceExtension
->AttachedDevice
)
2127 IoSkipCurrentIrpStackLocation(Irp
);
2128 Status
= IoCallDriver(DeviceExtension
->AttachedDevice
, Irp
);
2133 // Release the lock and return status
2136 IoReleaseRemoveLock(&DeviceExtension
->RemoveLock
, Irp
);
2142 RamdiskPower(IN PDEVICE_OBJECT DeviceObject
,
2147 return STATUS_SUCCESS
;
2152 RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject
,
2157 return STATUS_SUCCESS
;
2162 RamdiskScsi(IN PDEVICE_OBJECT DeviceObject
,
2167 return STATUS_SUCCESS
;
2172 RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject
,
2177 return STATUS_SUCCESS
;
2182 RamdiskUnload(IN PDRIVER_OBJECT DriverObject
)
2190 RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject
,
2191 IN PDEVICE_OBJECT PhysicalDeviceObject
)
2193 PRAMDISK_BUS_EXTENSION DeviceExtension
;
2194 PDEVICE_OBJECT AttachedDevice
;
2196 UNICODE_STRING DeviceName
;
2197 PDEVICE_OBJECT DeviceObject
;
2200 // Only create the bus FDO once
2202 if (RamdiskBusFdo
) return STATUS_DEVICE_ALREADY_ATTACHED
;
2205 // Create the bus FDO
2207 RtlInitUnicodeString(&DeviceName
, L
"\\Device\\Ramdisk");
2208 Status
= IoCreateDevice(DriverObject
,
2209 sizeof(RAMDISK_BUS_EXTENSION
),
2211 FILE_DEVICE_BUS_EXTENDER
,
2212 FILE_DEVICE_SECURE_OPEN
,
2215 if (NT_SUCCESS(Status
))
2218 // Initialize the bus FDO extension
2220 DeviceExtension
= DeviceObject
->DeviceExtension
;
2221 RtlZeroMemory(DeviceObject
->DeviceExtension
,
2222 sizeof(RAMDISK_BUS_EXTENSION
));
2225 // Set bus FDO flags
2227 DeviceObject
->Flags
|= DO_POWER_PAGABLE
| DO_DIRECT_IO
;
2230 // Setup the bus FDO extension
2232 DeviceExtension
->Type
= RamdiskBus
;
2233 ExInitializeFastMutex(&DeviceExtension
->DiskListLock
);
2234 IoInitializeRemoveLock(&DeviceExtension
->RemoveLock
,
2238 InitializeListHead(&DeviceExtension
->DiskList
);
2239 DeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
2240 DeviceExtension
->DeviceObject
= DeviceObject
;
2243 // Register the RAM disk device interface
2245 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
,
2246 &RamdiskBusInterface
,
2248 &DeviceExtension
->BusDeviceName
);
2249 if (!NT_SUCCESS(Status
))
2254 IoDeleteDevice(DeviceObject
);
2259 // Attach us to the device stack
2261 AttachedDevice
= IoAttachDeviceToDeviceStack(DeviceObject
,
2262 PhysicalDeviceObject
);
2263 DeviceExtension
->AttachedDevice
= AttachedDevice
;
2264 if (!AttachedDevice
)
2269 IoSetDeviceInterfaceState(&DeviceExtension
->BusDeviceName
, 0);
2270 RtlFreeUnicodeString(&DeviceExtension
->BusDeviceName
);
2271 IoDeleteDevice(DeviceObject
);
2272 return STATUS_NO_SUCH_DEVICE
;
2276 // Bus FDO is initialized
2278 RamdiskBusFdo
= DeviceObject
;
2281 // Loop for loader block
2286 // Are we being booted from setup? Not yet supported
2288 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2294 DeviceObject
->Flags
&= DO_DEVICE_INITIALIZING
;
2295 Status
= STATUS_SUCCESS
;
2306 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
2307 IN PUNICODE_STRING RegistryPath
)
2309 PCHAR BootDeviceName
, CommandLine
;
2310 PDEVICE_OBJECT PhysicalDeviceObject
= NULL
;
2312 DPRINT("RAM Disk Driver Initialized\n");
2315 // Query ramdisk parameters
2317 QueryParameters(RegistryPath
);
2320 // Save the registry path
2322 DriverRegistryPath
= *RegistryPath
;
2323 DriverRegistryPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
2324 RegistryPath
->Length
+
2327 if (!DriverRegistryPath
.Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2328 RtlCopyUnicodeString(&DriverRegistryPath
, RegistryPath
);
2331 // Set device routines
2333 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = RamdiskOpenClose
;
2334 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = RamdiskOpenClose
;
2335 DriverObject
->MajorFunction
[IRP_MJ_READ
] = RamdiskReadWrite
;
2336 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = RamdiskReadWrite
;
2337 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = RamdiskDeviceControl
;
2338 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = RamdiskPnp
;
2339 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = RamdiskPower
;
2340 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = RamdiskSystemControl
;
2341 DriverObject
->MajorFunction
[IRP_MJ_SCSI
] = RamdiskScsi
;
2342 DriverObject
->MajorFunction
[IRP_MJ_FLUSH_BUFFERS
] = RamdiskFlushBuffers
;
2343 DriverObject
->DriverExtension
->AddDevice
= RamdiskAddDevice
;
2344 DriverObject
->DriverUnload
= RamdiskUnload
;
2347 // Check for a loader block
2352 // Get the boot device name
2354 BootDeviceName
= KeLoaderBlock
->ArcBootDeviceName
;
2358 // Check if we're booting from ramdisk
2360 if ((strlen(BootDeviceName
) >= 10) &&
2361 !(_strnicmp(BootDeviceName
, "ramdisk(0)", 10)))
2364 // We'll have to tell the PnP Manager
2366 ReportDetectedDevice
= TRUE
;
2369 // Check for a command line
2371 CommandLine
= KeLoaderBlock
->LoadOptions
;
2375 // Check if this is an ISO boot
2377 if (strstr(CommandLine
, "RDEXPORTASCD"))
2380 // Remember for later
2382 ExportBootDiskAsCd
= TRUE
;
2386 // Check if this is PE boot
2388 if (strstr(CommandLine
, "MININT"))
2391 // Remember for later
2402 // Installing from Ramdisk isn't supported yet
2404 //ASSERT(!KeLoaderBlock->SetupLdrBlock);
2407 // Are we reporting the device
2409 if (ReportDetectedDevice
)
2414 Status
= IoReportDetectedDevice(DriverObject
,
2415 InterfaceTypeUndefined
,
2421 &PhysicalDeviceObject
);
2422 if (NT_SUCCESS(Status
))
2426 // The ReactOS Plug and Play Manager is broken and does not create
2427 // the required keys when reporting a detected device.
2428 // We hack around this ourselves.
2430 RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION
)
2431 PhysicalDeviceObject
->DeviceObjectExtension
)
2432 ->DeviceNode
->InstancePath
,
2433 L
"Root\\UNKNOWN\\0000");
2436 // Create the device object
2438 Status
= RamdiskAddDevice(DriverObject
, PhysicalDeviceObject
);
2439 if (NT_SUCCESS(Status
))
2444 PhysicalDeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
2445 Status
= STATUS_SUCCESS
;
2454 Status
= STATUS_SUCCESS
;