#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 DriveDeviceName; \
- UNICODE_STRING BusDeviceName; \
- 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;
- LONGLONG DiskLength;
+ 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;
}
}
+PVOID
+NTAPI
+RamdiskMapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
+ IN LARGE_INTEGER Offset,
+ IN ULONG Length,
+ OUT PULONG OutputLength)
+{
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PVOID MappedBase;
+ ULONG PageOffset;
+ SIZE_T ActualLength;
+ LARGE_INTEGER ActualOffset;
+ LARGE_INTEGER ActualPages;
+
+ //
+ // 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;
+
+ //
+ // Convert to pages
+ //
+ 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;
+}
+
+VOID
+NTAPI
+RamdiskUnmapPages(IN PRAMDISK_DRIVE_EXTENSION DeviceExtension,
+ IN PVOID BaseAddress,
+ IN LARGE_INTEGER Offset,
+ IN ULONG Length)
+{
+ 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
NTAPI
RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
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
Length = GuidString.Length + 32;
Buffer = ExAllocatePoolWithTag(NonPagedPool,
Length,
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
if (!Buffer)
{
//
DeviceName.MaximumLength = Length;
wcsncpy(Buffer, L"\\Device\\Ramdisk", Length / sizeof(WCHAR));
wcsncat(Buffer, GuidString.Buffer, Length / sizeof(WCHAR));
- DPRINT1("Creating device: %wZ\n", &DeviceName);
//
// Create the drive device
Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
sizeof(RAMDISK_DRIVE_EXTENSION),
&DeviceName,
- FILE_DEVICE_DISK_FILE_SYSTEM, // FIXME: DISK
- FILE_READ_ONLY_DEVICE, // FIXME: Not always
+ (Input->Options.ExportAsCd) ?
+ FILE_DEVICE_CD_ROM : FILE_DEVICE_DISK,
+ 0,
0,
&DeviceObject);
if (!NT_SUCCESS(Status)) goto FailCreate;
SymbolicLinkName.Length = GuidString.Length + 34;
Buffer = ExAllocatePoolWithTag(NonPagedPool,
SymbolicLinkName.MaximumLength,
- TAG('R', 'a', 'm', 'd'));
+ 'dmaR');
SymbolicLinkName.Buffer = Buffer;
if (Buffer)
{
wcsncat(Buffer,
GuidString.Buffer,
SymbolicLinkName.MaximumLength / sizeof(WCHAR));
- DPRINT1("Creating symbolic link: %wZ to %wZ \n",
- &SymbolicLinkName, &DeviceName);
Status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
if (!NT_SUCCESS(Status))
{
//
// It this an ISO boot ramdisk?
//
- if (Input->DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
+ if (Input->DiskType == RAMDISK_BOOT_DISK)
{
//
// Does it need a drive letter?
L"\\DosDevices\\%wc:",
Input->DriveLetter);
RtlInitUnicodeString(&DriveString, LocalBuffer);
- DPRINT1("Creating symbolic link: %wZ to %wZ\n",
- &DriveString, &DeviceName);
IoDeleteSymbolicLink(&DriveString);
IoCreateSymbolicLink(&DriveString, &DeviceName);
//
*NewDriveExtension = DriveExtension;
DriveExtension->Type = RamdiskDrive;
+ DiskLength = Input->DiskLength;
ExInitializeFastMutex(&DriveExtension->DiskListLock);
IoInitializeRemoveLock(&DriveExtension->RemoveLock,
- TAG('R', 'a', 'm', 'd'),
+ 'dmaR',
0,
1);
DriveExtension->DriveDeviceName = DeviceName;
DriveExtension->AttachedDevice = RamdiskBusFdo;
DriveExtension->DiskType = Input->DiskType;
DriveExtension->DiskOptions = Input->Options;
- DriveExtension->DiskLength = Input->DiskLength;
+ 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;
// 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
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
- return IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+ return;
}
//
//
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
- return IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
NTSTATUS
}
}
+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,
RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_SUCCESS;
+ 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
NTSTATUS Status;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
- ULONG Information = 0;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension = (PVOID)DeviceExtension;
+ ULONG Information;
+ PCDROM_TOC Toc;
+ PDISK_GEOMETRY DiskGeometry;
//
// Grab the remove lock
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);
//
// 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