#include <initguid.h>
#include <ntddk.h>
+#include <ntifs.h>
#include <ntdddisk.h>
+#include <ntddcdrm.h>
#include <scsi.h>
#include <ntddscsi.h>
+#include <ntddvol.h>
#include <mountdev.h>
#include <mountmgr.h>
-#include <helper.h>
#include <ketypes.h>
#include <iotypes.h>
#include <rtlfuncs.h>
#include <arc/arc.h>
#include <reactos/drivers/ntddrdsk.h>
+#include "../../../filesystems/fs_rec/fs_rec.h"
+#include <stdio.h>
#define NDEBUG
#include <debug.h>
+#define DO_XIP 0x00020000
+
/* GLOBALS ********************************************************************/
+#define RAMDISK_SESSION_SIZE \
+ FIELD_OFFSET(CDROM_TOC, TrackData) + sizeof(TRACK_DATA)
+
+#define RAMDISK_TOC_SIZE \
+ FIELD_OFFSET(CDROM_TOC, TrackData) + 2 * sizeof(TRACK_DATA)
+
+#define TOC_DATA_TRACK (0x04)
+
typedef enum _RAMDISK_DEVICE_TYPE
{
RamdiskBus,
0x410F,
0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
-//
-// GCC does not seem to support anonymous structures
-//
-#define RAMDISK_EXTENSION \
- RAMDISK_DEVICE_TYPE Type; \
- RAMDISK_DEVICE_STATE State; \
- PDEVICE_OBJECT DeviceObject; \
- PDEVICE_OBJECT PhysicalDeviceObject; \
- PDEVICE_OBJECT AttachedDevice; \
- IO_REMOVE_LOCK RemoveLock; \
- UNICODE_STRING SymbolicLinkName; \
- FAST_MUTEX DiskListLock; \
+typedef struct _RAMDISK_EXTENSION
+{
+ RAMDISK_DEVICE_TYPE Type;
+ RAMDISK_DEVICE_STATE State;
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT PhysicalDeviceObject;
+ PDEVICE_OBJECT AttachedDevice;
+ IO_REMOVE_LOCK RemoveLock;
+ UNICODE_STRING DriveDeviceName;
+ UNICODE_STRING BusDeviceName;
+ FAST_MUTEX DiskListLock;
LIST_ENTRY DiskList;
+} RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
typedef struct _RAMDISK_BUS_EXTENSION
{
typedef struct _RAMDISK_DRIVE_EXTENSION
{
+ //
+ // Inherited base class
+ //
RAMDISK_EXTENSION;
+
+ //
+ // Data we get from the creator
+ //
+ GUID DiskGuid;
+ UNICODE_STRING GuidString;
+ UNICODE_STRING SymbolicLinkName;
+ ULONG DiskType;
+ RAMDISK_CREATE_OPTIONS DiskOptions;
+ LARGE_INTEGER DiskLength;
+ LONG DiskOffset;
+ WCHAR DriveLetter;
+ ULONG BasePage;
+
+ //
+ // Data we get from the disk
+ //
+ ULONG BytesPerSector;
+ ULONG SectorsPerTrack;
+ ULONG NumberOfHeads;
+ ULONG Cylinders;
+ ULONG HiddenSectors;
} RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
ULONG MaximumViewLength;
}
}
-VOID
-NTAPI
-RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
- IN PVOID Context)
-{
- UNIMPLEMENTED;
- while (TRUE);
-}
-
-NTSTATUS
+PVOID
NTAPI
-SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
+ IN LARGE_INTEGER Offset,
+ IN ULONG Length,
+ OUT PULONG OutputLength)
{
- PIO_WORKITEM WorkItem;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID MappedBase;
+ ULONG PageOffset;
+ SIZE_T ActualLength;
+ LARGE_INTEGER ActualOffset;
+ LARGE_INTEGER ActualPages;
//
- // Mark the IRP pending
+ // We only support boot disks for now
//
- IoMarkIrpPending(Irp);
+ ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
//
- // Allocate a work item
+ // Calculate the actual offset in the drive
//
- WorkItem = IoAllocateWorkItem(DeviceObject);
- if (WorkItem)
- {
- //
- // Queue it up
- //
- Irp->Tail.Overlay.DriverContext[0] = WorkItem;
- IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
- return STATUS_PENDING;
- }
- else
- {
- //
- // Fail
- //
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-}
-
-NTSTATUS
-NTAPI
-RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
+ ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
+
//
- // Complete the IRP
+ // Convert to pages
//
- Irp->IoStatus.Information = 1;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return STATUS_SUCCESS;
+ ActualPages.QuadPart = ActualOffset.QuadPart >> PAGE_SHIFT;
+
+ //
+ // Now add the base page
+ //
+ ActualPages.QuadPart = DeviceExtension->BasePage + ActualPages.QuadPart;
+
+ //
+ // Calculate final amount of bytes
+ //
+ PhysicalAddress.QuadPart = ActualPages.QuadPart << PAGE_SHIFT;
+
+ //
+ // Calculate pages spanned for the mapping
+ //
+ ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
+
+ //
+ // And convert this back to bytes
+ //
+ ActualLength <<= PAGE_SHIFT;
+
+ //
+ // Get the offset within the page
+ //
+ PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
+
+ //
+ // Map the I/O Space from the loader
+ //
+ MappedBase = MmMapIoSpace(PhysicalAddress, ActualLength, MmCached);
+
+ //
+ // Return actual offset within the page as well as the length
+ //
+ if (MappedBase) MappedBase = (PVOID)((ULONG_PTR)MappedBase + PageOffset);
+ *OutputLength = Length;
+ return MappedBase;
}
-NTSTATUS
+VOID
NTAPI
-RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
+ IN PVOID BaseAddress,
+ IN LARGE_INTEGER Offset,
+ IN ULONG Length)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_SUCCESS;
+ LARGE_INTEGER ActualOffset;
+ SIZE_T ActualLength;
+ ULONG PageOffset;
+
+ //
+ // We only support boot disks for now
+ //
+ ASSERT(DeviceExtension->DiskType == RAMDISK_BOOT_DISK);
+
+ //
+ // Calculate the actual offset in the drive
+ //
+ ActualOffset.QuadPart = DeviceExtension->DiskOffset + Offset.QuadPart;
+
+ //
+ // Calculate pages spanned for the mapping
+ //
+ ActualLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(ActualOffset.QuadPart, Length);
+
+ //
+ // And convert this back to bytes
+ //
+ ActualLength <<= PAGE_SHIFT;
+
+ //
+ // Get the offset within the page
+ //
+ PageOffset = BYTE_OFFSET(ActualOffset.QuadPart);
+
+ //
+ // Calculate actual base address where we mapped this
+ //
+ BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - PageOffset);
+
+ //
+ // Unmap the I/O space we got from the loader
+ //
+ MmUnmapIoSpace(BaseAddress, ActualLength);
}
NTSTATUS
RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
IN PRAMDISK_CREATE_INPUT Input,
IN BOOLEAN ValidateOnly,
- OUT PDEVICE_OBJECT *DeviceObject)
+ OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
{
- ULONG BasePage, ViewCount, DiskType;
+ ULONG BasePage, ViewCount, DiskType, Length;
+ NTSTATUS Status;
+ PDEVICE_OBJECT DeviceObject;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension;
+ PVOID Buffer;
+ WCHAR LocalBuffer[16];
+ UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
+ PPACKED_BOOT_SECTOR BootSector;
+ BIOS_PARAMETER_BLOCK BiosBlock;
+ ULONG BytesPerSector, SectorsPerTrack, Heads, BytesRead;
+ PVOID BaseAddress;
+ LARGE_INTEGER CurrentOffset, CylinderSize, DiskLength;
+ ULONG CylinderCount, SizeByCylinders;
//
- // Check if we're a CDROM-type RAM disk
+ // Check if we're a boot RAM disk
//
DiskType = Input->DiskType;
- if (DiskType > FILE_DEVICE_CD_ROM)
+ if (DiskType >= RAMDISK_BOOT_DISK)
{
//
// Check if we're an ISO
//
- if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
+ if (DiskType == RAMDISK_BOOT_DISK)
{
//
// NTLDR mounted us somewhere
else
{
//
- // The only other possibility is a controller
+ // The only other possibility is a WIM disk
//
- if (DiskType != FILE_DEVICE_CONTROLLER)
+ if (DiskType != RAMDISK_WIM_DISK)
+ {
+ //
+ // Fail
+ //
return STATUS_INVALID_PARAMETER;
+ }
//
// Read the view count instead
if (ValidateOnly) return STATUS_SUCCESS;
//
- // FIXME-TODO: Implement the rest of the code
+ // Build the GUID string
//
- }
+ Status = RtlStringFromGUID(&Input->DiskGuid, &GuidString);
+ if (!(NT_SUCCESS(Status)) || !(GuidString.Buffer))
+ {
+ //
+ // Fail
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto FailCreate;
+ }
+
+ //
+ // Allocate our device name
+ //
+ Length = GuidString.Length + 32;
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
+ 'dmaR');
+ if (!Buffer)
+ {
+ //
+ // Fail
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto FailCreate;
+ }
+
+ //
+ // Build the device name string
+ //
+ DeviceName.Buffer = Buffer;
+ DeviceName.Length = Length - 2;
+ DeviceName.MaximumLength = Length;
+ wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
+ wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
+
+ //
+ // Create the drive device
+ //
+ Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
+ sizeof(RAMDISK_DRIVE_EXTENSION),
+ &DeviceName,
+ (Input->Options.ExportAsCd) ?
+ FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
+ 0,
+ 0,
+ &DeviceObject);
+ if (!NT_SUCCESS(Status)) goto FailCreate;
+
+ //
+ // Grab the drive extension
+ //
+ DriveExtension = DeviceObject->DeviceExtension;
+
+ //
+ // Check if we need a DOS device
+ //
+ if (!Input->Options.NoDosDevice)
+ {
+ //
+ // Build the symbolic link name
+ //
+ SymbolicLinkName.MaximumLength = GuidString.Length + 36;
+ SymbolicLinkName.Length = GuidString.Length + 34;
+ Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ SymbolicLinkName.MaximumLength,
+ 'dmaR');
+ SymbolicLinkName.Buffer = Buffer;
+ if (Buffer)
+ {
+ //
+ // Create it
+ //
+ wcsncpy(Buffer,
+ L"\\GLOBAL??\\Ramdisk",
+ SymbolicLinkName.MaximumLength / sizeof(WCHAR));
+ wcsncat(Buffer,
+ GuidString.Buffer,
+ SymbolicLinkName.MaximumLength / sizeof(WCHAR));
+ Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
+ if (!NT_SUCCESS(Status))
+ {
+ //
+ // Nevermind...
+ //
+ Input->Options.NoDosDevice = TRUE;
+ ExFreePool(Buffer);
+ SymbolicLinkName.Buffer = NULL;
+ }
+ }
+ else
+ {
+ //
+ // No DOS device
+ //
+ Input->Options.NoDosDevice = TRUE;
+ }
+
+ //
+ // It this an ISO boot ramdisk?
+ //
+ if (Input->DiskType == RAMDISK_BOOT_DISK)
+ {
+ //
+ // Does it need a drive letter?
+ //
+ if (!Input->Options.NoDriveLetter)
+ {
+ //
+ // Build it and take over the existing symbolic link
+ //
+ _snwprintf(LocalBuffer,
+ 30,
+ L"\\DosDevices\\%wc:",
+ Input->DriveLetter);
+ RtlInitUnicodeString(&DriveString, LocalBuffer);
+ IoDeleteSymbolicLink(&DriveString);
+ IoCreateSymbolicLink(&DriveString, &DeviceName);
+
+ //
+ // Save the drive letter
+ //
+ DriveExtension->DriveLetter = Input->DriveLetter;
+ }
+ }
+
+ }
+
+ //
+ // Setup the device object flags
+ //
+ DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
+ DeviceObject->AlignmentRequirement = 1;
+
+ //
+ // Build the drive FDO
+ //
+ *NewDriveExtension = DriveExtension;
+ DriveExtension->Type = RamdiskDrive;
+ DiskLength = Input->DiskLength;
+ ExInitializeFastMutex(&DriveExtension->DiskListLock);
+ IoInitializeRemoveLock(&DriveExtension->RemoveLock,
+ 'dmaR',
+ 0,
+ 1);
+ DriveExtension->DriveDeviceName = DeviceName;
+ DriveExtension->SymbolicLinkName = SymbolicLinkName;
+ DriveExtension->GuidString = GuidString;
+ DriveExtension->DiskGuid = Input->DiskGuid;
+ DriveExtension->PhysicalDeviceObject = DeviceObject;
+ DriveExtension->DeviceObject = RamdiskBusFdo;
+ DriveExtension->AttachedDevice = RamdiskBusFdo;
+ DriveExtension->DiskType = Input->DiskType;
+ DriveExtension->DiskOptions = Input->Options;
+ DriveExtension->DiskLength = DiskLength;
+ DriveExtension->DiskOffset = Input->DiskOffset;
+ DriveExtension->BasePage = Input->BasePage;
+ DriveExtension->BytesPerSector = 0;
+ DriveExtension->SectorsPerTrack = 0;
+ DriveExtension->NumberOfHeads = 0;
+
+ //
+ // Make sure we don't free it later
+ //
+ DeviceName.Buffer = NULL;
+ SymbolicLinkName.Buffer = NULL;
+ GuidString.Buffer = NULL;
+
+ //
+ // Check if this is an boot disk, or a registry ram drive
+ //
+ if (!(Input->Options.ExportAsCd) &&
+ (Input->DiskType == RAMDISK_BOOT_DISK))
+ {
+ //
+ // Not an ISO boot, but it's a boot FS -- map it to figure out the
+ // drive settings
+ //
+ CurrentOffset.QuadPart = 0;
+ BaseAddress = RamdiskMapPages(DriveExtension,
+ CurrentOffset,
+ PAGE_SIZE,
+ &BytesRead);
+ if (BaseAddress)
+ {
+ //
+ // Get the data
+ //
+ BootSector = (PPACKED_BOOT_SECTOR)BaseAddress;
+ FatUnpackBios(&BiosBlock, &BootSector->PackedBpb);
+ BytesPerSector = BiosBlock.BytesPerSector;
+ SectorsPerTrack = BiosBlock.SectorsPerTrack;
+ Heads = BiosBlock.Heads;
+
+ //
+ // Save it
+ //
+ DriveExtension->BytesPerSector = BytesPerSector;
+ DriveExtension->SectorsPerTrack = SectorsPerTrack;
+ DriveExtension->NumberOfHeads = Heads;
+
+ //
+ // Unmap now
+ //
+ CurrentOffset.QuadPart = 0;
+ RamdiskUnmapPages(DriveExtension,
+ BaseAddress,
+ CurrentOffset,
+ BytesRead);
+ }
+ else
+ {
+ //
+ // Fail
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto FailCreate;
+ }
+ }
+
+ //
+ // Check if the drive settings haven't been set yet
+ //
+ if ((DriveExtension->BytesPerSector == 0) ||
+ (DriveExtension->SectorsPerTrack == 0) ||
+ (DriveExtension->NumberOfHeads == 0))
+ {
+ //
+ // Check if this is a CD
+ //
+ if (Input->Options.ExportAsCd)
+ {
+ //
+ // Setup partition parameters default for ISO 9660
+ //
+ DriveExtension->BytesPerSector = 2048;
+ DriveExtension->SectorsPerTrack = 32;
+ DriveExtension->NumberOfHeads = 64;
+ }
+ else
+ {
+ //
+ // Setup partition parameters default for FAT
+ //
+ DriveExtension->BytesPerSector = 512;
+ DriveExtension->SectorsPerTrack = 128;
+ DriveExtension->NumberOfHeads = 16;
+ }
+ }
+
+ //
+ // Calculate the cylinder size
+ //
+ CylinderSize.QuadPart = DriveExtension->BytesPerSector *
+ DriveExtension->SectorsPerTrack *
+ DriveExtension->NumberOfHeads;
+ CylinderCount = DiskLength.QuadPart / CylinderSize.QuadPart;
+ SizeByCylinders = CylinderSize.QuadPart * CylinderCount;
+ DriveExtension->Cylinders = CylinderCount;
+ if ((DiskLength.HighPart > 0) || (SizeByCylinders < DiskLength.LowPart))
+ {
+ //
+ // Align cylinder size up
+ //
+ DriveExtension->Cylinders++;
+ }
+
+ //
+ // Acquire the disk lock
+ //
+ KeEnterCriticalRegion();
+ ExAcquireFastMutex(&DeviceExtension->DiskListLock);
+
+ //
+ // Insert us
+ //
+ InsertTailList(&DeviceExtension->DiskList, &DriveExtension->DiskList);
+
+ //
+ // Release the lock
+ //
+ ExReleaseFastMutex(&DeviceExtension->DiskListLock);
+ KeLeaveCriticalRegion();
+
+ //
+ // Clear init flag
+ //
+ DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+ return STATUS_SUCCESS;
+ }
+FailCreate:
UNIMPLEMENTED;
while (TRUE);
return STATUS_SUCCESS;
{
PRAMDISK_CREATE_INPUT Input;
ULONG Length;
- PRAMDISK_BUS_EXTENSION DeviceExtension;
+ PRAMDISK_BUS_EXTENSION DeviceExtension;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension;
ULONG DiskType;
PWCHAR FileNameStart, FileNameEnd;
NTSTATUS Status;
// Validate the disk type
//
DiskType = Input->DiskType;
- if (DiskType == FILE_DEVICE_CONTROLLER) return STATUS_INVALID_PARAMETER;
+ if (DiskType == RAMDISK_WIM_DISK) return STATUS_INVALID_PARAMETER;
//
// Look at the disk type
//
- if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
+ if (DiskType == RAMDISK_BOOT_DISK)
{
//
// We only allow this as an early-init boot
//
// Validate the disk type
//
- if ((Input->Options.ExportAsCd) &&
- (DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
+ if ((Input->Options.ExportAsCd) && (DiskType != RAMDISK_BOOT_DISK))
{
//
// If the type isn't CDFS, it has to at least be raw CD
//
- if (DiskType != FILE_DEVICE_CD_ROM) return STATUS_INVALID_PARAMETER;
+ if (DiskType != RAMDISK_MEMORY_MAPPED_DISK) return STATUS_INVALID_PARAMETER;
}
//
// Check if this is an actual file
//
- if (DiskType <= FILE_DEVICE_CD_ROM)
+ if (DiskType <= RAMDISK_MEMORY_MAPPED_DISK)
{
//
// Validate the file name
Status = RamdiskCreateDiskDevice(DeviceExtension,
Input,
ValidateOnly,
- &DeviceObject);
+ &DriveExtension);
if (NT_SUCCESS(Status))
{
//
return Status;
}
-NTSTATUS
+VOID
NTAPI
-RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
+ IN PVOID Context)
{
+ PRAMDISK_BUS_EXTENSION DeviceExtension;
NTSTATUS Status;
- PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
- PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
- ULONG Information = 0;
+ PIO_STACK_LOCATION IoStackLocation;
+ PIRP Irp = Context;
//
- // Grab the remove lock
+ // Get the stack location
+ //
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // Free the work item
+ //
+ IoFreeWorkItem(Irp->Tail.Overlay.DriverContext[0]);
+
+ //
+ // Grab the device extension and lock it
//
+ DeviceExtension = DeviceObject->DeviceExtension;
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
- if (!NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
+ {
+ //
+ // Discriminate by major code
+ //
+ switch (IoStackLocation->MajorFunction)
+ {
+ //
+ // Device control
+ //
+ case IRP_MJ_DEVICE_CONTROL:
+
+ //
+ // Let's take a look at the IOCTL
+ //
+ switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
+ {
+ //
+ // Ramdisk create request
+ //
+ case FSCTL_CREATE_RAM_DISK:
+
+ //
+ // This time we'll do it for real
+ //
+ Status = RamdiskCreateRamdisk(DeviceObject, Irp, FALSE);
+ break;
+
+ case IOCTL_DISK_SET_PARTITION_INFO:
+
+ DPRINT1("Set partition info request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_DISK_GET_DRIVE_LAYOUT:
+
+ DPRINT1("Get drive layout request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_DISK_GET_PARTITION_INFO:
+
+ DPRINT1("Get partitinon info request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ default:
+
+ DPRINT1("Invalid request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+ }
+
+ //
+ // We're here
+ //
+ break;
+
+ //
+ // Read or write request
+ //
+ case IRP_MJ_READ:
+ case IRP_MJ_WRITE:
+
+ DPRINT1("Read/Write request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ //
+ // Internal request (SCSI?)
+ //
+ case IRP_MJ_INTERNAL_DEVICE_CONTROL:
+
+ DPRINT1("SCSI request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ //
+ // Flush request
+ //
+ case IRP_MJ_FLUSH_BUFFERS:
+
+ DPRINT1("Flush request\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ //
+ // Anything else
+ //
+ default:
+
+ DPRINT1("Invalid request: %lx\n", IoStackLocation->MajorFunction);
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+ }
+
+ //
+ // Complete the I/O
+ //
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ return;
+ }
+
+ //
+ // Fail the I/O
+ //
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+}
+
+NTSTATUS
+NTAPI
+SendIrpToThread(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_WORKITEM WorkItem;
+
+ //
+ // Mark the IRP pending
+ //
+ IoMarkIrpPending(Irp);
+
+ //
+ // Allocate a work item
+ //
+ WorkItem = IoAllocateWorkItem(DeviceObject);
+ if (WorkItem)
+ {
+ //
+ // Queue it up
+ //
+ Irp->Tail.Overlay.DriverContext[0] = WorkItem;
+ IoQueueWorkItem(WorkItem, RamdiskWorkerThread, DelayedWorkQueue, Irp);
+ return STATUS_PENDING;
+ }
+ else
+ {
+ //
+ // Fail
+ //
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+}
+
+NTSTATUS
+NTAPI
+RamdiskReadWriteReal(IN PIRP Irp,
+ IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
+{
+ PMDL Mdl;
+ PVOID CurrentBase, SystemVa, BaseAddress;
+ PIO_STACK_LOCATION IoStackLocation;
+ LARGE_INTEGER CurrentOffset;
+ ULONG BytesRead, BytesLeft, CopyLength;
+ PVOID Source, Destination;
+ NTSTATUS Status;
+
+ //
+ // Get the MDL and check if it's mapped
+ //
+ Mdl = Irp->MdlAddress;
+ if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))
+ {
+ //
+ // Use the mapped address
+ //
+ SystemVa = Mdl->MappedSystemVa;
+ }
+ else
+ {
+ //
+ // Map it ourselves
+ //
+ SystemVa = MmMapLockedPagesSpecifyCache(Mdl,
+ 0,
+ MmCached,
+ NULL,
+ 0,
+ NormalPagePriority);
+ }
+
+ //
+ // Make sure we were able to map it
+ //
+ CurrentBase = SystemVa;
+ if (!SystemVa) return STATUS_INSUFFICIENT_RESOURCES;
+
+ //
+ // Initialize default
+ //
+ Irp->IoStatus.Information = 0;
+
+ //
+ // Get the I/O Stack Location and capture the data
+ //
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ CurrentOffset = IoStackLocation->Parameters.Read.ByteOffset;
+ BytesLeft = IoStackLocation->Parameters.Read.Length;
+ if (!BytesLeft) return STATUS_INVALID_PARAMETER;
+
+ //
+ // Do the copy loop
+ //
+ while (TRUE)
+ {
+ //
+ // Map the pages
+ //
+ BaseAddress = RamdiskMapPages(DeviceExtension,
+ CurrentOffset,
+ BytesLeft,
+ &BytesRead);
+ if (!BaseAddress) return STATUS_INSUFFICIENT_RESOURCES;
+
+ //
+ // Update our lengths
+ //
+ Irp->IoStatus.Information += BytesRead;
+ CopyLength = BytesRead;
+
+ //
+ // Check if this was a read or write
+ //
+ Status = STATUS_SUCCESS;
+ if (IoStackLocation->MajorFunction == IRP_MJ_READ)
+ {
+ //
+ // Set our copy parameters
+ //
+ Destination = CurrentBase;
+ Source = BaseAddress;
+ goto DoCopy;
+ }
+ else if (IoStackLocation->MajorFunction == IRP_MJ_WRITE)
+ {
+ //
+ // Set our copy parameters
+ //
+ Destination = BaseAddress;
+ Source = CurrentBase;
+DoCopy:
+ //
+ // Copy the data
+ //
+ RtlCopyMemory(Destination, Source, CopyLength);
+ }
+ else
+ {
+ //
+ // Prepare us for failure
+ //
+ BytesLeft = CopyLength;
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ //
+ // Unmap the pages
+ //
+ RamdiskUnmapPages(DeviceExtension,
+ BaseAddress,
+ CurrentOffset,
+ BytesRead);
+
+ //
+ // Update offset and bytes left
+ //
+ BytesLeft -= BytesRead;
+ CurrentOffset.QuadPart += BytesRead;
+ CurrentBase = (PVOID)((ULONG_PTR)CurrentBase + BytesRead);
+
+ //
+ // Check if we're done
+ //
+ if (!BytesLeft) return Status;
+ }
+}
+
+NTSTATUS
+NTAPI
+RamdiskGetPartitionInfo(IN PIRP Irp,
+ IN PRAMDISK_DRIVE_EXTENSION DeviceExtension)
+{
+ NTSTATUS Status;
+ PPARTITION_INFORMATION PartitionInfo;
+ PVOID BaseAddress;
+ LARGE_INTEGER Zero = {{0, 0}};
+ ULONG Length;
+ PIO_STACK_LOCATION IoStackLocation;
+
+ //
+ // Validate the length
+ //
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(PARTITION_INFORMATION))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ return Status;
+ }
+
+ //
+ // Map the partition table
+ //
+ BaseAddress = RamdiskMapPages(DeviceExtension, Zero, PAGE_SIZE, &Length);
+ if (!BaseAddress)
+ {
+ //
+ // No memory
+ //
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ return Status;
+ }
+
+ //
+ // Fill out the information
+ //
+ PartitionInfo = Irp->AssociatedIrp.SystemBuffer;
+ PartitionInfo->StartingOffset.QuadPart = DeviceExtension->BytesPerSector;
+ PartitionInfo->PartitionLength.QuadPart = DeviceExtension->BytesPerSector *
+ DeviceExtension->SectorsPerTrack *
+ DeviceExtension->NumberOfHeads *
+ DeviceExtension->Cylinders;
+ PartitionInfo->HiddenSectors = DeviceExtension->HiddenSectors;
+ PartitionInfo->PartitionNumber = 0;
+ PartitionInfo->PartitionType = PARTITION_FAT32; //*((PCHAR)BaseAddress + 450);
+ PartitionInfo->BootIndicator = (DeviceExtension->DiskType ==
+ RAMDISK_BOOT_DISK) ? TRUE: FALSE;
+ PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartitionInfo->
+ PartitionType);
+ PartitionInfo->RewritePartition = FALSE;
+
+ //
+ // Unmap the partition table
+ //
+ RamdiskUnmapPages(DeviceExtension, BaseAddress, Zero, Length);
+
+ //
+ // Done
+ //
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ //
+ // Complete the IRP
+ //
+ Irp->IoStatus.Information = 1;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PRAMDISK_DRIVE_EXTENSION DeviceExtension;
+ ULONG Length;
+ LARGE_INTEGER ByteOffset;
+ PIO_STACK_LOCATION IoStackLocation;
+ NTSTATUS Status, ReturnStatus;
+
+ //
+ // Get the device extension and make sure this isn't a bus
+ //
+ DeviceExtension = DeviceObject->DeviceExtension;
+ if (DeviceExtension->Type == RamdiskBus)
+ {
+ //
+ // Fail
+ //
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ goto Complete;
+ }
+
+ //
+ // Capture parameters
+ //
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ Length = IoStackLocation->Parameters.Read.Length;
+ ByteOffset = IoStackLocation->Parameters.Read.ByteOffset;
+
+ //
+ // FIXME: Validate offset
+ //
+
+ //
+ // FIXME: Validate sector
+ //
+
+ //
+ // Validate write
+ //
+ if ((IoStackLocation->MajorFunction == IRP_MJ_WRITE) &&
+ (DeviceExtension->DiskOptions.Readonly))
+ {
+ //
+ // Fail, this is read-only
+ //
+ Status = STATUS_MEDIA_WRITE_PROTECTED;
+ goto Complete;
+ }
+
+ //
+ // See if we want to do this sync or async
+ //
+ if (DeviceExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
+ {
+ //
+ // Do it sync
+ //
+ Status = RamdiskReadWriteReal(Irp, DeviceExtension);
+ goto Complete;
+ }
+
+ //
+ // Queue it to the worker
+ //
+ Status = SendIrpToThread(DeviceObject, Irp);
+ ReturnStatus = STATUS_PENDING;
+
+ //
+ // Check if we're pending or not
+ //
+ if (Status != STATUS_PENDING)
+ {
+Complete:
+ //
+ // Complete the IRP
+ //
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ ReturnStatus = Status;
+ }
+
+ //
+ // Return to caller
+ //
+ return ReturnStatus;
+}
+
+NTSTATUS
+NTAPI
+RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
+ ULONG Information;
+ PCDROM_TOC Toc;
+ PDISK_GEOMETRY DiskGeometry;
+
+ //
+ // Grab the remove lock
+ //
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ if (!NT_SUCCESS(Status))
{
//
// Fail the IRP
return Status;
}
+ //
+ // Setup some defaults
+ //
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ Information = 0;
+
//
// Check if this is an bus device or the drive
//
else
{
//
- // Drive code not yet done
+ // Check what the request is
+ //
+ switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_DISK_CHECK_VERIFY:
+ case IOCTL_STORAGE_CHECK_VERIFY:
+ case IOCTL_STORAGE_CHECK_VERIFY2:
+ case IOCTL_CDROM_CHECK_VERIFY:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_STORAGE_GET_MEDIA_TYPES:
+ case IOCTL_DISK_GET_MEDIA_TYPES:
+ case IOCTL_DISK_GET_DRIVE_GEOMETRY:
+ case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
+
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(DISK_GEOMETRY))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Fill it out
+ //
+ DiskGeometry = Irp->AssociatedIrp.SystemBuffer;
+ DiskGeometry->Cylinders.QuadPart = DriveExtension->Cylinders;
+ DiskGeometry->BytesPerSector = DriveExtension->BytesPerSector;
+ DiskGeometry->SectorsPerTrack = DriveExtension->SectorsPerTrack;
+ DiskGeometry->TracksPerCylinder = DriveExtension->NumberOfHeads;
+ DiskGeometry->MediaType = DriveExtension->DiskOptions.Fixed ?
+ FixedMedia : RemovableMedia;
+
+ //
+ // We're done
+ //
+ Status = STATUS_SUCCESS;
+ Information = sizeof(DISK_GEOMETRY);
+ break;
+
+ //
+ // Hack to support ReactOS's broken CDFS
+ //
+ case IOCTL_CDROM_GET_LAST_SESSION:
+
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < RAMDISK_SESSION_SIZE)
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Fill out the TOC
+ //
+ Toc = Irp->AssociatedIrp.SystemBuffer;
+ Toc->Length[0] = 0;
+ Toc->Length[1] = RAMDISK_SESSION_SIZE - sizeof(Toc->Length);
+ Toc->FirstTrack = 1;
+ Toc->LastTrack = 1;
+ Toc->TrackData[0].Adr = 1;
+ Toc->TrackData[0].Control = TOC_DATA_TRACK;
+ Toc->TrackData[0].TrackNumber = 1;
+ Toc->TrackData[0].Address[0] =
+ Toc->TrackData[0].Address[1] =
+ Toc->TrackData[0].Address[2] =
+ Toc->TrackData[0].Address[3] = 0;
+
+ //
+ // We're done
+ //
+ Status = STATUS_SUCCESS;
+ Information = RAMDISK_SESSION_SIZE;
+ break;
+
+ case IOCTL_CDROM_READ_TOC:
+
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(CDROM_TOC))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Clear the TOC
+ //
+ Toc = Irp->AssociatedIrp.SystemBuffer;
+ RtlZeroMemory(Toc, sizeof(CDROM_TOC));
+
+ //
+ // Fill it out
+ //
+ Toc->Length[0] = 0;
+ Toc->Length[1] = RAMDISK_TOC_SIZE - sizeof(Toc->Length);
+ Toc->FirstTrack = 1;
+ Toc->LastTrack = 1;
+ Toc->TrackData[0].Adr = 1;
+ Toc->TrackData[0].Control = TOC_DATA_TRACK;
+ Toc->TrackData[0].TrackNumber = 1;
+
+ //
+ // We're done
+ //
+ Status = STATUS_SUCCESS;
+ Information = RAMDISK_TOC_SIZE;
+ break;
+
+ case IOCTL_DISK_SET_PARTITION_INFO:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_DISK_GET_PARTITION_INFO:
+
+ //
+ // Validate the length
+ //
+ if (IoStackLocation->Parameters.DeviceIoControl.
+ OutputBufferLength < sizeof(PARTITION_INFORMATION))
+ {
+ //
+ // Invalid length
+ //
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // Check if we need to do this sync or async
+ //
+ if (DriveExtension->DiskType > RAMDISK_MEMORY_MAPPED_DISK)
+ {
+ //
+ // Call the helper function
+ //
+ Status = RamdiskGetPartitionInfo(Irp, DriveExtension);
+ }
+ else
+ {
+ //
+ // Do it asynchronously later
+ //
+ goto CallWorker;
+ }
+
+ //
+ // We're done
+ //
+ Information = Irp->IoStatus.Information;
+ break;
+
+ case IOCTL_DISK_GET_DRIVE_LAYOUT:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_DISK_GET_LENGTH_INFO:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_DISK_IS_WRITABLE:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_SCSI_MINIPORT:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_STORAGE_QUERY_PROPERTY:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_VOLUME_SET_GPT_ATTRIBUTES:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_VOLUME_GET_GPT_ATTRIBUTES:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ case IOCTL_VOLUME_OFFLINE:
+
+ UNIMPLEMENTED;
+ while (TRUE);
+ break;
+
+ default:
+
+ //
+ // Drive code not emulated
+ //
+ DPRINT1("IOCTL: %lx\n", IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
+ break;
+ }
+
+ //
+ // If requests drop down here, we just return them complete them
//
- ASSERT(FALSE);
+ goto CompleteRequest;
}
//
// Queue the request to our worker thread
//
+CallWorker:
Status = SendIrpToThread(DeviceObject, Irp);
CompleteRequest:
Objects) +
FinalCount *
sizeof(PDEVICE_OBJECT),
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!OurDeviceRelations)
{
//
DeviceExtension->Type = RamdiskBus;
ExInitializeFastMutex(&DeviceExtension->DiskListLock);
IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
- TAG('R', 'a', 'm', 'd'),
+ 'dmaR',
0,
1);
InitializeListHead(&DeviceExtension->DiskList);
Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
&RamdiskBusInterface,
NULL,
- &DeviceExtension->SymbolicLinkName);
+ &DeviceExtension->BusDeviceName);
if (!NT_SUCCESS(Status))
{
//
//
// Fail
//
- IoSetDeviceInterfaceState(&DeviceExtension->SymbolicLinkName, 0);
- RtlFreeUnicodeString(&DeviceExtension->SymbolicLinkName);
+ IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
+ RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
IoDeleteDevice(DeviceObject);
return STATUS_NO_SUCH_DEVICE;
}
//
// Are we being booted from setup? Not yet supported
//
- ASSERT (!KeLoaderBlock->SetupLdrBlock);
+ //ASSERT(!KeLoaderBlock->SetupLdrBlock);
}
//
PCHAR BootDeviceName, CommandLine;
PDEVICE_OBJECT PhysicalDeviceObject = NULL;
NTSTATUS Status;
+ DPRINT("RAM Disk Driver Initialized\n");
//
// Query ramdisk parameters
DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
RegistryPath->Length +
sizeof(WCHAR),
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
//
// Installing from Ramdisk isn't supported yet
//
- ASSERT(!KeLoaderBlock->SetupLdrBlock);
+ //ASSERT(!KeLoaderBlock->SetupLdrBlock);
//
// Are we reporting the device