2008-06-29 02:58:05 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: Ramdisk Class Driver
|
2008-06-30 08:54:30 +00:00
|
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
2008-06-29 02:58:05 +00:00
|
|
|
* FILE: drivers/storage/class/ramdisk/ramdisk.c
|
|
|
|
* PURPOSE: Main Driver Routines
|
|
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
2008-07-13 04:23:59 +00:00
|
|
|
#include <initguid.h>
|
2008-06-29 02:58:05 +00:00
|
|
|
#include <ntddk.h>
|
|
|
|
#include <ntdddisk.h>
|
2008-07-20 06:32:23 +00:00
|
|
|
#include <ntddcdrm.h>
|
2008-06-29 02:58:05 +00:00
|
|
|
#include <scsi.h>
|
|
|
|
#include <ntddscsi.h>
|
2008-07-20 16:13:19 +00:00
|
|
|
#include <ntddvol.h>
|
2008-06-29 02:58:05 +00:00
|
|
|
#include <mountdev.h>
|
|
|
|
#include <mountmgr.h>
|
|
|
|
#include <helper.h>
|
|
|
|
#include <ketypes.h>
|
2008-07-13 04:23:59 +00:00
|
|
|
#include <iotypes.h>
|
|
|
|
#include <rtlfuncs.h>
|
2008-06-29 02:58:05 +00:00
|
|
|
#include <arc/arc.h>
|
2008-07-13 04:23:59 +00:00
|
|
|
#include <reactos/drivers/ntddrdsk.h>
|
2008-07-19 22:21:38 +00:00
|
|
|
#include <stdio.h>
|
2008-06-29 02:58:05 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
2008-07-13 04:23:59 +00:00
|
|
|
typedef enum _RAMDISK_DEVICE_TYPE
|
|
|
|
{
|
2008-07-19 18:44:31 +00:00
|
|
|
RamdiskBus,
|
|
|
|
RamdiskDrive
|
2008-07-13 04:23:59 +00:00
|
|
|
} RAMDISK_DEVICE_TYPE;
|
|
|
|
|
2008-07-13 07:02:48 +00:00
|
|
|
typedef enum _RAMDISK_DEVICE_STATE
|
|
|
|
{
|
|
|
|
RamdiskStateUninitialized,
|
|
|
|
RamdiskStateStarted,
|
2008-07-13 07:16:24 +00:00
|
|
|
RamdiskStatePaused,
|
2008-07-13 07:02:48 +00:00
|
|
|
RamdiskStateStopped,
|
2008-07-13 07:16:24 +00:00
|
|
|
RamdiskStateRemoved,
|
|
|
|
RamdiskStateBusRemoved,
|
2008-07-19 18:44:31 +00:00
|
|
|
RamdiskStateEnumerated,
|
2008-07-13 07:02:48 +00:00
|
|
|
} RAMDISK_DEVICE_STATE;
|
|
|
|
|
2008-07-13 04:23:59 +00:00
|
|
|
DEFINE_GUID(RamdiskBusInterface,
|
|
|
|
0x5DC52DF0,
|
|
|
|
0x2F8A,
|
|
|
|
0x410F,
|
|
|
|
0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
|
|
|
|
|
2008-07-20 19:39:55 +00:00
|
|
|
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;
|
2008-07-19 18:44:31 +00:00
|
|
|
LIST_ENTRY DiskList;
|
2008-07-20 19:39:55 +00:00
|
|
|
} RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
|
2008-07-19 18:44:31 +00:00
|
|
|
|
|
|
|
typedef struct _RAMDISK_BUS_EXTENSION
|
2008-07-13 04:23:59 +00:00
|
|
|
{
|
2008-07-19 18:44:31 +00:00
|
|
|
RAMDISK_EXTENSION;
|
|
|
|
} RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
|
|
|
|
|
|
|
|
typedef struct _RAMDISK_DRIVE_EXTENSION
|
|
|
|
{
|
|
|
|
RAMDISK_EXTENSION;
|
2008-07-19 22:42:18 +00:00
|
|
|
GUID DiskGuid;
|
|
|
|
UNICODE_STRING GuidString;
|
|
|
|
UNICODE_STRING SymbolicLinkName;
|
|
|
|
ULONG DiskType;
|
|
|
|
RAMDISK_CREATE_OPTIONS DiskOptions;
|
|
|
|
LONGLONG DiskLength;
|
|
|
|
LONG DiskOffset;
|
2008-07-19 22:21:38 +00:00
|
|
|
WCHAR DriveLetter;
|
2008-07-20 04:39:01 +00:00
|
|
|
ULONG BytesPerSector;
|
|
|
|
ULONG SectorsPerTrack;
|
|
|
|
ULONG NumberOfHeads;
|
2008-07-19 18:44:31 +00:00
|
|
|
} RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
|
2008-07-13 04:23:59 +00:00
|
|
|
|
2008-06-29 02:58:05 +00:00
|
|
|
ULONG MaximumViewLength;
|
|
|
|
ULONG MaximumPerDiskViewLength;
|
|
|
|
ULONG ReportDetectedDevice;
|
|
|
|
ULONG MarkRamdisksAsRemovable;
|
|
|
|
ULONG MinimumViewCount;
|
|
|
|
ULONG DefaultViewCount;
|
|
|
|
ULONG MaximumViewCount;
|
|
|
|
ULONG MinimumViewLength;
|
|
|
|
ULONG DefaultViewLength;
|
|
|
|
UNICODE_STRING DriverRegistryPath;
|
|
|
|
BOOLEAN ExportBootDiskAsCd;
|
|
|
|
BOOLEAN IsWinPEBoot;
|
2008-07-13 04:23:59 +00:00
|
|
|
PDEVICE_OBJECT RamdiskBusFdo;
|
2008-06-29 02:58:05 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
QueryParameters(IN PUNICODE_STRING RegistryPath)
|
|
|
|
{
|
|
|
|
ULONG MinView, DefView, MinViewLength, DefViewLength, MaxViewLength;
|
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[10];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set defaults
|
|
|
|
//
|
|
|
|
MaximumViewLength = 0x10000000u;
|
|
|
|
MaximumPerDiskViewLength = 0x10000000u;
|
|
|
|
ReportDetectedDevice = 0;
|
|
|
|
MarkRamdisksAsRemovable = 0;
|
|
|
|
MinimumViewCount = 2;
|
|
|
|
DefaultViewCount = 16;
|
|
|
|
MaximumViewCount = 64;
|
|
|
|
MinimumViewLength = 0x10000u;
|
|
|
|
DefaultViewLength = 0x100000u;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Setup the query table and query the registry
|
|
|
|
//
|
|
|
|
RtlZeroMemory(QueryTable, sizeof(QueryTable));
|
|
|
|
QueryTable[0].Flags = 1;
|
|
|
|
QueryTable[0].Name = L"Parameters";
|
|
|
|
QueryTable[1].Flags = 32;
|
|
|
|
QueryTable[1].Name = L"ReportDetectedDevice";
|
|
|
|
QueryTable[1].EntryContext = &ReportDetectedDevice;
|
|
|
|
QueryTable[2].Flags = 32;
|
|
|
|
QueryTable[2].Name = L"MarkRamdisksAsRemovable";
|
|
|
|
QueryTable[2].EntryContext = &MarkRamdisksAsRemovable;
|
|
|
|
QueryTable[3].Flags = 32;
|
|
|
|
QueryTable[3].Name = L"MinimumViewCount";
|
|
|
|
QueryTable[3].EntryContext = &MinimumViewCount;
|
|
|
|
QueryTable[4].Flags = 32;
|
|
|
|
QueryTable[4].Name = L"DefaultViewCount";
|
|
|
|
QueryTable[4].EntryContext = &DefaultViewCount;
|
|
|
|
QueryTable[5].Flags = 32;
|
|
|
|
QueryTable[5].Name = L"MaximumViewCount";
|
|
|
|
QueryTable[5].EntryContext = &MaximumViewCount;
|
|
|
|
QueryTable[6].Flags = 32;
|
|
|
|
QueryTable[6].Name = L"MinimumViewLength";
|
|
|
|
QueryTable[6].EntryContext = &MinimumViewLength;
|
|
|
|
QueryTable[7].Flags = 32;
|
|
|
|
QueryTable[7].Name = L"DefaultViewLength";
|
|
|
|
QueryTable[7].EntryContext = &DefaultViewLength;
|
|
|
|
QueryTable[8].Flags = 32;
|
|
|
|
QueryTable[8].Name = L"MaximumViewLength";
|
|
|
|
QueryTable[8].EntryContext = &MaximumViewLength;
|
|
|
|
QueryTable[9].Flags = 32;
|
|
|
|
QueryTable[9].Name = L"MaximumPerDiskViewLength";
|
|
|
|
QueryTable[9].EntryContext = &MaximumPerDiskViewLength;
|
|
|
|
RtlQueryRegistryValues(RTL_REGISTRY_OPTIONAL,
|
|
|
|
RegistryPath->Buffer,
|
|
|
|
QueryTable,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse minimum view count, cannot be bigger than 256 or smaller than 2
|
|
|
|
//
|
|
|
|
MinView = MinimumViewCount;
|
|
|
|
if (MinimumViewCount >= 2)
|
|
|
|
{
|
|
|
|
if (MinimumViewCount > 256) MinView = 256;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MinView = 2;
|
|
|
|
}
|
|
|
|
MinimumViewCount = MinView;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse default view count, cannot be bigger than 256 or smaller than minimum
|
|
|
|
//
|
|
|
|
DefView = DefaultViewCount;
|
|
|
|
if (DefaultViewCount >= MinView)
|
|
|
|
{
|
|
|
|
if (DefaultViewCount > 256) DefView = 256;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DefView = MinView;
|
|
|
|
}
|
|
|
|
DefaultViewCount = DefView;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse maximum view count, cannot be bigger than 256 or smaller than default
|
|
|
|
//
|
|
|
|
if (MaximumViewCount >= DefView)
|
|
|
|
{
|
|
|
|
if (MaximumViewCount > 256) MaximumViewCount = 256;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MaximumViewCount = DefView;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse minimum view length, cannot be bigger than 1GB or smaller than 64KB
|
|
|
|
//
|
|
|
|
MinViewLength = MinimumViewLength;
|
|
|
|
if (MinimumViewLength >= 0x10000)
|
|
|
|
{
|
|
|
|
if (MinimumViewLength > 0x40000000) MinViewLength = 0x40000000u;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MinViewLength = 0x10000u;
|
|
|
|
}
|
|
|
|
MinimumViewLength = MinViewLength;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse default view length, cannot be bigger than 1GB or smaller than minimum
|
|
|
|
//
|
|
|
|
DefViewLength = DefaultViewLength;
|
|
|
|
if (DefaultViewLength >= MinViewLength)
|
|
|
|
{
|
|
|
|
if (DefaultViewLength > 0x40000000) DefViewLength = 0x40000000u;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DefViewLength = MinViewLength;
|
|
|
|
}
|
|
|
|
DefaultViewLength = DefViewLength;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse maximum view length, cannot be bigger than 1GB or smaller than default
|
|
|
|
//
|
|
|
|
MaxViewLength = MaximumViewLength;
|
|
|
|
if (MaximumViewLength >= DefViewLength)
|
|
|
|
{
|
|
|
|
if (MaximumViewLength > 0x40000000) MaxViewLength = 0x40000000u;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MaxViewLength = DefViewLength;
|
|
|
|
}
|
|
|
|
MaximumViewLength = MaxViewLength;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Parse maximum view length per disk, cannot be smaller than 16MB
|
|
|
|
//
|
|
|
|
if (MaximumPerDiskViewLength >= 0x1000000)
|
|
|
|
{
|
|
|
|
if (MaxViewLength > 0xFFFFFFFF) MaximumPerDiskViewLength = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MaximumPerDiskViewLength = 0x1000000u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-13 07:37:36 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2008-07-19 18:44:31 +00:00
|
|
|
RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
|
2008-07-13 07:37:36 +00:00
|
|
|
IN PRAMDISK_CREATE_INPUT Input,
|
|
|
|
IN BOOLEAN ValidateOnly,
|
2008-07-19 22:42:18 +00:00
|
|
|
OUT PRAMDISK_DRIVE_EXTENSION *NewDriveExtension)
|
2008-07-13 07:37:36 +00:00
|
|
|
{
|
2008-07-19 22:21:38 +00:00
|
|
|
ULONG BasePage, ViewCount, DiskType, Length;
|
|
|
|
NTSTATUS Status;
|
2008-07-19 22:42:18 +00:00
|
|
|
PDEVICE_OBJECT DeviceObject;
|
2008-07-19 22:21:38 +00:00
|
|
|
PRAMDISK_DRIVE_EXTENSION DriveExtension;
|
|
|
|
PVOID Buffer;
|
|
|
|
WCHAR LocalBuffer[16];
|
|
|
|
UNICODE_STRING SymbolicLinkName, DriveString, GuidString, DeviceName;
|
2008-07-19 18:44:31 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Check if we're a CDROM-type RAM disk
|
|
|
|
//
|
|
|
|
DiskType = Input->DiskType;
|
|
|
|
if (DiskType > FILE_DEVICE_CD_ROM)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if we're an ISO
|
|
|
|
//
|
|
|
|
if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// NTLDR mounted us somewhere
|
|
|
|
//
|
|
|
|
BasePage = Input->BasePage;
|
|
|
|
if (!BasePage) return STATUS_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Sanitize disk options
|
|
|
|
//
|
|
|
|
Input->Options.Fixed = TRUE;
|
|
|
|
Input->Options.Readonly = Input->Options.ExportAsCd |
|
|
|
|
Input->Options.Readonly;
|
|
|
|
Input->Options.Hidden = FALSE;
|
|
|
|
Input->Options.NoDosDevice = FALSE;
|
|
|
|
Input->Options.NoDriveLetter = IsWinPEBoot ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// The only other possibility is a controller
|
|
|
|
//
|
|
|
|
if (DiskType != FILE_DEVICE_CONTROLLER)
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read the view count instead
|
|
|
|
//
|
|
|
|
ViewCount = Input->ViewCount;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Sanitize disk options
|
|
|
|
//
|
|
|
|
Input->Options.Hidden = FALSE;
|
|
|
|
Input->Options.NoDosDevice = FALSE;
|
|
|
|
Input->Options.Readonly = FALSE;
|
|
|
|
Input->Options.NoDriveLetter = TRUE;
|
|
|
|
Input->Options.Fixed = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Are we just validating and returning to the user?
|
|
|
|
//
|
|
|
|
if (ValidateOnly) return STATUS_SUCCESS;
|
|
|
|
|
2008-07-19 22:21:38 +00:00
|
|
|
//
|
|
|
|
// 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,
|
|
|
|
TAG('R', 'a', 'm', 'd'));
|
|
|
|
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));
|
|
|
|
DPRINT1("Creating device: %wZ\n", &DeviceName);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create the drive device
|
|
|
|
//
|
|
|
|
Status = IoCreateDevice(DeviceExtension->DeviceObject->DriverObject,
|
|
|
|
sizeof(RAMDISK_DRIVE_EXTENSION),
|
|
|
|
&DeviceName,
|
2008-07-20 06:32:23 +00:00
|
|
|
FILE_DEVICE_CD_ROM,
|
|
|
|
0,
|
2008-07-19 22:21:38 +00:00
|
|
|
0,
|
2008-07-19 22:42:18 +00:00
|
|
|
&DeviceObject);
|
2008-07-19 22:21:38 +00:00
|
|
|
if (!NT_SUCCESS(Status)) goto FailCreate;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Grab the drive extension
|
|
|
|
//
|
2008-07-19 22:42:18 +00:00
|
|
|
DriveExtension = DeviceObject->DeviceExtension;
|
2008-07-19 22:21:38 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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,
|
|
|
|
TAG('R', 'a', 'm', 'd'));
|
|
|
|
SymbolicLinkName.Buffer = Buffer;
|
|
|
|
if (Buffer)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Create it
|
|
|
|
//
|
|
|
|
wcsncpy(Buffer,
|
|
|
|
L"\\GLOBAL??\\Ramdisk",
|
|
|
|
SymbolicLinkName.MaximumLength / sizeof(WCHAR));
|
|
|
|
wcsncat(Buffer,
|
|
|
|
GuidString.Buffer,
|
|
|
|
SymbolicLinkName.MaximumLength / sizeof(WCHAR));
|
2008-07-19 22:42:18 +00:00
|
|
|
DPRINT1("Creating symbolic link: %wZ to %wZ \n",
|
|
|
|
&SymbolicLinkName, &DeviceName);
|
2008-07-19 22:21:38 +00:00
|
|
|
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 == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// 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);
|
2008-07-19 22:42:18 +00:00
|
|
|
DPRINT1("Creating symbolic link: %wZ to %wZ\n",
|
|
|
|
&DriveString, &DeviceName);
|
2008-07-19 22:21:38 +00:00
|
|
|
IoDeleteSymbolicLink(&DriveString);
|
|
|
|
IoCreateSymbolicLink(&DriveString, &DeviceName);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save the drive letter
|
|
|
|
//
|
|
|
|
DriveExtension->DriveLetter = Input->DriveLetter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-07-19 18:44:31 +00:00
|
|
|
//
|
2008-07-19 22:42:18 +00:00
|
|
|
// Setup the device object flags
|
2008-07-19 18:44:31 +00:00
|
|
|
//
|
2008-07-19 22:42:18 +00:00
|
|
|
DeviceObject->Flags |= (DO_XIP | DO_POWER_PAGABLE | DO_DIRECT_IO);
|
|
|
|
DeviceObject->AlignmentRequirement = 1;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Build the drive FDO
|
|
|
|
//
|
|
|
|
*NewDriveExtension = DriveExtension;
|
|
|
|
DriveExtension->Type = RamdiskDrive;
|
|
|
|
ExInitializeFastMutex(&DriveExtension->DiskListLock);
|
|
|
|
IoInitializeRemoveLock(&DriveExtension->RemoveLock,
|
|
|
|
TAG('R', 'a', 'm', 'd'),
|
|
|
|
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 = Input->DiskLength;
|
|
|
|
DriveExtension->DiskOffset = Input->DiskOffset;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Make sure we don't free it later
|
|
|
|
//
|
|
|
|
DeviceName.Buffer = NULL;
|
|
|
|
SymbolicLinkName.Buffer = NULL;
|
|
|
|
GuidString.Buffer = NULL;
|
2008-07-20 04:39:01 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Only support ISO stuff for now
|
|
|
|
//
|
|
|
|
ASSERT(Input->Options.ExportAsCd == TRUE);
|
|
|
|
ASSERT(Input->DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Setup partition parameters
|
|
|
|
//
|
|
|
|
DriveExtension->BytesPerSector = 2048; // 512 for Disk
|
|
|
|
DriveExtension->SectorsPerTrack = 32; // 128 for disk
|
|
|
|
DriveExtension->NumberOfHeads = 64; // 16 for disk
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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;
|
|
|
|
}
|
2008-07-19 18:44:31 +00:00
|
|
|
|
2008-07-19 22:21:38 +00:00
|
|
|
FailCreate:
|
2008-07-13 07:37:36 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp,
|
|
|
|
IN BOOLEAN ValidateOnly)
|
|
|
|
{
|
|
|
|
PRAMDISK_CREATE_INPUT Input;
|
|
|
|
ULONG Length;
|
2008-07-19 22:42:18 +00:00
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension;
|
|
|
|
PRAMDISK_DRIVE_EXTENSION DriveExtension;
|
2008-07-13 07:37:36 +00:00
|
|
|
ULONG DiskType;
|
|
|
|
PWCHAR FileNameStart, FileNameEnd;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the device extension and our input data
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
2008-07-13 07:37:36 +00:00
|
|
|
Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
|
|
|
|
Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Validate input parameters
|
|
|
|
//
|
|
|
|
if ((Length < sizeof(RAMDISK_CREATE_INPUT)) ||
|
|
|
|
(Input->Version != sizeof(RAMDISK_CREATE_INPUT)))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Invalid input
|
|
|
|
//
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Validate the disk type
|
|
|
|
//
|
|
|
|
DiskType = Input->DiskType;
|
|
|
|
if (DiskType == FILE_DEVICE_CONTROLLER) return STATUS_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Look at the disk type
|
|
|
|
//
|
|
|
|
if (DiskType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We only allow this as an early-init boot
|
|
|
|
//
|
|
|
|
if (!KeLoaderBlock) return STATUS_INVALID_PARAMETER;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save command-line flags
|
|
|
|
//
|
|
|
|
if (ExportBootDiskAsCd) Input->Options.ExportAsCd = TRUE;
|
|
|
|
if (IsWinPEBoot) Input->Options.NoDriveLetter = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Validate the disk type
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if ((Input->Options.ExportAsCd) &&
|
|
|
|
(DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
|
2008-07-13 07:37:36 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// If the type isn't CDFS, it has to at least be raw CD
|
|
|
|
//
|
|
|
|
if (DiskType != FILE_DEVICE_CD_ROM) return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if this is an actual file
|
|
|
|
//
|
|
|
|
if (DiskType <= FILE_DEVICE_CD_ROM)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Validate the file name
|
|
|
|
//
|
|
|
|
FileNameStart = (PWCHAR)((ULONG_PTR)Input + Length);
|
|
|
|
FileNameEnd = Input->FileName + 1;
|
|
|
|
while ((FileNameEnd < FileNameStart) && *(FileNameEnd)) FileNameEnd++;
|
|
|
|
if (FileNameEnd == FileNameStart) return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Create the actual device
|
|
|
|
//
|
|
|
|
Status = RamdiskCreateDiskDevice(DeviceExtension,
|
|
|
|
Input,
|
|
|
|
ValidateOnly,
|
2008-07-19 22:42:18 +00:00
|
|
|
&DriveExtension);
|
2008-07-13 07:37:36 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Invalidate and set success
|
|
|
|
//
|
|
|
|
IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, 0);
|
|
|
|
Irp->IoStatus.Information = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// We're done
|
|
|
|
//
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2008-07-19 21:19:41 +00:00
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PVOID Context)
|
|
|
|
{
|
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PIO_STACK_LOCATION IoStackLocation;
|
|
|
|
PIRP Irp = Context;
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// 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;
|
|
|
|
return IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Fail the I/O
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
return 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
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-06-29 02:58:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
2008-07-13 07:37:36 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
2008-07-19 18:44:31 +00:00
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
2008-07-20 16:13:19 +00:00
|
|
|
ULONG Information;
|
2008-07-13 07:37:36 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Grab the remove lock
|
|
|
|
//
|
|
|
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail the IRP
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2008-07-20 16:13:19 +00:00
|
|
|
//
|
|
|
|
// Setup some defaults
|
|
|
|
//
|
|
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
Information = 0;
|
|
|
|
|
2008-07-13 07:37:36 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Check if this is an bus device or the drive
|
2008-07-13 07:37:36 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskBus)
|
2008-07-13 07:37:36 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check what the request is
|
|
|
|
//
|
|
|
|
switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Request to create a ramdisk
|
|
|
|
//
|
|
|
|
case FSCTL_CREATE_RAM_DISK:
|
|
|
|
|
|
|
|
//
|
|
|
|
// Do it
|
|
|
|
//
|
|
|
|
Status = RamdiskCreateRamdisk(DeviceObject, Irp, TRUE);
|
|
|
|
if (!NT_SUCCESS(Status)) goto CompleteRequest;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
//
|
|
|
|
// We don't handle anything else yet
|
|
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
2008-07-20 06:32:23 +00:00
|
|
|
// Check what the request is
|
|
|
|
//
|
|
|
|
switch (IoStackLocation->Parameters.DeviceIoControl.IoControlCode)
|
|
|
|
{
|
2008-07-20 16:13:19 +00:00
|
|
|
case IOCTL_DISK_CHECK_VERIFY:
|
|
|
|
case IOCTL_STORAGE_CHECK_VERIFY:
|
|
|
|
case IOCTL_STORAGE_CHECK_VERIFY2:
|
2008-07-20 06:32:23 +00:00
|
|
|
case IOCTL_CDROM_CHECK_VERIFY:
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
2008-07-20 16:13:19 +00:00
|
|
|
|
|
|
|
case IOCTL_STORAGE_GET_MEDIA_TYPES:
|
|
|
|
case IOCTL_DISK_GET_MEDIA_TYPES:
|
|
|
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
|
2008-07-20 06:32:23 +00:00
|
|
|
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IOCTL_CDROM_READ_TOC:
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
2008-07-20 16:13:19 +00:00
|
|
|
case IOCTL_DISK_SET_PARTITION_INFO:
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IOCTL_DISK_GET_PARTITION_INFO:
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
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;
|
|
|
|
|
2008-07-20 06:32:23 +00:00
|
|
|
default:
|
|
|
|
|
|
|
|
//
|
2008-07-20 16:13:19 +00:00
|
|
|
// Drive code not emulated
|
2008-07-20 06:32:23 +00:00
|
|
|
//
|
|
|
|
DPRINT1("IOCTL: %lx\n", IoStackLocation->Parameters.DeviceIoControl.IoControlCode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2008-07-20 16:13:19 +00:00
|
|
|
// If requests drop down here, we just return them complete them
|
2008-07-13 07:37:36 +00:00
|
|
|
//
|
2008-07-20 16:13:19 +00:00
|
|
|
goto CompleteRequest;
|
2008-07-13 07:37:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Queue the request to our worker thread
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
Status = SendIrpToThread(DeviceObject, Irp);
|
2008-07-13 07:37:36 +00:00
|
|
|
|
|
|
|
CompleteRequest:
|
|
|
|
//
|
|
|
|
// Release the lock
|
|
|
|
//
|
|
|
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
|
|
|
|
if (Status != STATUS_PENDING)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Complete the request
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
Irp->IoStatus.Information = Information;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return status
|
|
|
|
//
|
|
|
|
return Status;
|
2008-06-29 02:58:05 +00:00
|
|
|
}
|
|
|
|
|
2008-07-19 18:44:31 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskQueryDeviceRelations(IN DEVICE_RELATION_TYPE Type,
|
|
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension;
|
|
|
|
PRAMDISK_DRIVE_EXTENSION DriveExtension;
|
|
|
|
PDEVICE_RELATIONS DeviceRelations, OurDeviceRelations;
|
|
|
|
ULONG Count, DiskCount, FinalCount;
|
|
|
|
PLIST_ENTRY ListHead, NextEntry;
|
|
|
|
PDEVICE_OBJECT* DriveDeviceObject;
|
|
|
|
RAMDISK_DEVICE_STATE State;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the device extension and check if this is a drive
|
|
|
|
//
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (DeviceExtension->Type == RamdiskDrive)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// FIXME: TODO
|
|
|
|
//
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Anything but bus relations, we don't handle
|
|
|
|
//
|
|
|
|
if (Type) goto PassToNext;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Acquire the disk list lock
|
|
|
|
//
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
ExAcquireFastMutex(&DeviceExtension->DiskListLock);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Did a device already fill relations?
|
|
|
|
//
|
|
|
|
DeviceRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
|
|
|
|
if (DeviceRelations)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Use the data
|
|
|
|
//
|
|
|
|
Count = DeviceRelations->Count;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We're the first
|
|
|
|
//
|
|
|
|
Count = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now loop our drives
|
|
|
|
//
|
|
|
|
DiskCount = 0;
|
|
|
|
ListHead = &DeviceExtension->DiskList;
|
|
|
|
NextEntry = ListHead->Flink;
|
|
|
|
while (NextEntry != ListHead)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// As long as it wasn't removed, count it in
|
|
|
|
//
|
|
|
|
DriveExtension = CONTAINING_RECORD(NextEntry,
|
|
|
|
RAMDISK_DRIVE_EXTENSION,
|
|
|
|
DiskList);
|
|
|
|
if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Move to the next one
|
|
|
|
//
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Now we know our final count
|
|
|
|
//
|
|
|
|
FinalCount = Count + DiskCount;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Allocate the structure
|
|
|
|
//
|
|
|
|
OurDeviceRelations = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
FIELD_OFFSET(DEVICE_RELATIONS,
|
|
|
|
Objects) +
|
|
|
|
FinalCount *
|
|
|
|
sizeof(PDEVICE_OBJECT),
|
|
|
|
TAG('R', 'a', 'm', 'd'));
|
|
|
|
if (!OurDeviceRelations)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
|
|
|
ExReleaseFastMutex(&DeviceExtension->DiskListLock);
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if we already had some relations
|
|
|
|
//
|
|
|
|
if (Count)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Copy them in
|
|
|
|
//
|
|
|
|
RtlCopyMemory(OurDeviceRelations->Objects,
|
|
|
|
DeviceRelations->Objects,
|
|
|
|
Count * sizeof(PDEVICE_OBJECT));
|
|
|
|
}
|
|
|
|
|
2008-07-19 20:57:31 +00:00
|
|
|
//
|
|
|
|
// Save the count
|
|
|
|
//
|
|
|
|
OurDeviceRelations->Count = FinalCount;
|
|
|
|
|
2008-07-19 18:44:31 +00:00
|
|
|
//
|
|
|
|
// Now loop our drives again
|
|
|
|
//
|
|
|
|
ListHead = &DeviceExtension->DiskList;
|
|
|
|
NextEntry = ListHead->Flink;
|
|
|
|
while (NextEntry != ListHead)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Go to the end of the list
|
|
|
|
//
|
|
|
|
DriveDeviceObject = &OurDeviceRelations->Objects[Count];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the drive state
|
|
|
|
//
|
|
|
|
DriveExtension = CONTAINING_RECORD(NextEntry,
|
|
|
|
RAMDISK_DRIVE_EXTENSION,
|
|
|
|
DiskList);
|
|
|
|
State = DriveExtension->State;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If it was removed or enumerated, we don't touch the device object
|
|
|
|
//
|
|
|
|
if (State >= RamdiskStateBusRemoved)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// If it was removed, we still have to keep track of this though
|
|
|
|
//
|
|
|
|
if (State == RamdiskStateBusRemoved)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Mark it as enumerated now, but don't actually reference it
|
|
|
|
//
|
|
|
|
DriveExtension->State = RamdiskStateEnumerated;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// First time it's enumerated, reference the device object
|
|
|
|
//
|
|
|
|
ObReferenceObject(DriveExtension->DeviceObject);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save the object pointer, and move on
|
|
|
|
//
|
|
|
|
*DriveDeviceObject++ = DriveExtension->DeviceObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DriveExtension->State < RamdiskStateBusRemoved) DiskCount++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Move to the next one
|
|
|
|
//
|
|
|
|
NextEntry = NextEntry->Flink;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Release the lock
|
|
|
|
//
|
|
|
|
ExReleaseFastMutex(&DeviceExtension->DiskListLock);
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
|
|
|
|
//
|
|
|
|
// Cleanup old relations
|
|
|
|
//
|
|
|
|
if (DeviceRelations) ExFreePool(DeviceRelations);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Complete our IRP
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)OurDeviceRelations;
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Pass to the next driver
|
|
|
|
//
|
|
|
|
PassToNext:
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
return IoCallDriver(DeviceExtension->AttachedDevice, Irp);
|
|
|
|
}
|
|
|
|
|
2008-06-29 02:58:05 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
2008-07-13 07:02:48 +00:00
|
|
|
PIO_STACK_LOCATION IoStackLocation;
|
2008-07-19 18:44:31 +00:00
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension;
|
2008-07-13 07:02:48 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
UCHAR Minor;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the device extension and stack location
|
|
|
|
//
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Minor = IoStackLocation->MinorFunction;
|
|
|
|
|
|
|
|
//
|
2008-07-13 07:16:24 +00:00
|
|
|
// Check if the bus is removed
|
2008-07-13 07:02:48 +00:00
|
|
|
//
|
2008-07-13 07:16:24 +00:00
|
|
|
if (DeviceExtension->State == RamdiskStateBusRemoved)
|
2008-07-13 07:02:48 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// Only remove-device and query-id are allowed
|
|
|
|
//
|
|
|
|
if ((Minor != IRP_MN_REMOVE_DEVICE) || (Minor != IRP_MN_QUERY_ID))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail anything else
|
|
|
|
//
|
|
|
|
Status = STATUS_NO_SUCH_DEVICE;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Acquire the remove lock
|
|
|
|
//
|
|
|
|
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail the IRP
|
|
|
|
//
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Query the IRP type
|
|
|
|
//
|
|
|
|
switch (Minor)
|
|
|
|
{
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
2008-07-13 07:16:24 +00:00
|
|
|
|
|
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
2008-07-13 07:02:48 +00:00
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
2008-07-13 07:16:24 +00:00
|
|
|
case IRP_MN_QUERY_ID:
|
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Are we a drive?
|
2008-07-13 07:16:24 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskDrive)
|
2008-07-13 07:16:24 +00:00
|
|
|
{
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
2008-07-13 07:33:31 +00:00
|
|
|
}
|
2008-07-13 07:16:24 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-13 07:02:48 +00:00
|
|
|
case IRP_MN_QUERY_BUS_INFORMATION:
|
|
|
|
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Are we a drive?
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskDrive)
|
2008-07-13 07:33:31 +00:00
|
|
|
{
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
}
|
2008-07-13 07:02:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_EJECT:
|
|
|
|
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
|
|
|
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Are we a drive?
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskDrive)
|
2008-07-13 07:33:31 +00:00
|
|
|
{
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
}
|
2008-07-13 07:02:48 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
|
|
|
2008-07-19 18:44:31 +00:00
|
|
|
//
|
|
|
|
// Call our main routine
|
|
|
|
//
|
|
|
|
Status = RamdiskQueryDeviceRelations(IoStackLocation->
|
|
|
|
Parameters.
|
|
|
|
QueryDeviceRelations.Type,
|
|
|
|
DeviceObject,
|
|
|
|
Irp);
|
|
|
|
goto ReleaseAndReturn;
|
2008-07-13 07:02:48 +00:00
|
|
|
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
|
|
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Are we a drive?
|
2008-07-13 07:33:31 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskDrive)
|
2008-07-13 07:33:31 +00:00
|
|
|
{
|
|
|
|
DPRINT1("PnP IRP: %lx\n", Minor);
|
|
|
|
while (TRUE);
|
|
|
|
}
|
2008-07-13 07:02:48 +00:00
|
|
|
break;
|
|
|
|
|
2008-07-13 07:33:31 +00:00
|
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
|
|
|
|
|
|
//
|
|
|
|
// Complete immediately without touching it
|
|
|
|
//
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
goto ReleaseAndReturn;
|
|
|
|
|
2008-07-13 07:02:48 +00:00
|
|
|
default:
|
|
|
|
|
|
|
|
DPRINT1("Illegal IRP: %lx\n", Minor);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-07-13 07:16:24 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Are we the bus?
|
2008-07-13 07:16:24 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
if (DeviceExtension->Type == RamdiskBus)
|
2008-07-13 07:16:24 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// Do we have an attached device?
|
|
|
|
//
|
|
|
|
if (DeviceExtension->AttachedDevice)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Forward the IRP
|
|
|
|
//
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-13 07:02:48 +00:00
|
|
|
//
|
|
|
|
// Release the lock and return status
|
|
|
|
//
|
2008-07-13 07:33:31 +00:00
|
|
|
ReleaseAndReturn:
|
2008-07-13 07:02:48 +00:00
|
|
|
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
|
|
|
|
return Status;
|
2008-06-29 02:58:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskPower(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskSystemControl(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskScsi(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
|
|
|
|
IN PIRP Irp)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
RamdiskUnload(IN PDRIVER_OBJECT DriverObject)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
while (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject)
|
|
|
|
{
|
2008-07-19 18:44:31 +00:00
|
|
|
PRAMDISK_BUS_EXTENSION DeviceExtension;
|
2008-07-13 04:23:59 +00:00
|
|
|
PDEVICE_OBJECT AttachedDevice;
|
|
|
|
NTSTATUS Status;
|
|
|
|
UNICODE_STRING DeviceName;
|
|
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Only create the bus FDO once
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
|
|
|
if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
|
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Create the bus FDO
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
|
|
|
RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
|
|
|
|
Status = IoCreateDevice(DriverObject,
|
2008-07-19 18:44:31 +00:00
|
|
|
sizeof(RAMDISK_BUS_EXTENSION),
|
2008-07-13 04:23:59 +00:00
|
|
|
&DeviceName,
|
|
|
|
FILE_DEVICE_BUS_EXTENDER,
|
|
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
|
|
0,
|
|
|
|
&DeviceObject);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Initialize the bus FDO extension
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
RtlZeroMemory(DeviceObject->DeviceExtension,
|
|
|
|
sizeof(RAMDISK_BUS_EXTENSION));
|
2008-07-13 04:23:59 +00:00
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Set bus FDO flags
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
|
|
|
DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
|
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Setup the bus FDO extension
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
DeviceExtension->Type = RamdiskBus;
|
2008-07-13 04:23:59 +00:00
|
|
|
ExInitializeFastMutex(&DeviceExtension->DiskListLock);
|
|
|
|
IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
|
|
|
|
TAG('R', 'a', 'm', 'd'),
|
|
|
|
0,
|
|
|
|
1);
|
2008-07-19 18:44:31 +00:00
|
|
|
InitializeListHead(&DeviceExtension->DiskList);
|
2008-07-13 04:23:59 +00:00
|
|
|
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
|
|
|
DeviceExtension->DeviceObject = DeviceObject;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Register the RAM disk device interface
|
|
|
|
//
|
|
|
|
Status = IoRegisterDeviceInterface(PhysicalDeviceObject,
|
|
|
|
&RamdiskBusInterface,
|
|
|
|
NULL,
|
2008-07-19 22:42:18 +00:00
|
|
|
&DeviceExtension->BusDeviceName);
|
2008-07-13 04:23:59 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Attach us to the device stack
|
|
|
|
//
|
|
|
|
AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
|
|
|
|
PhysicalDeviceObject);
|
|
|
|
DeviceExtension->AttachedDevice = AttachedDevice;
|
|
|
|
if (!AttachedDevice)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Fail
|
|
|
|
//
|
2008-07-19 22:42:18 +00:00
|
|
|
IoSetDeviceInterfaceState(&DeviceExtension->BusDeviceName, 0);
|
|
|
|
RtlFreeUnicodeString(&DeviceExtension->BusDeviceName);
|
2008-07-13 04:23:59 +00:00
|
|
|
IoDeleteDevice(DeviceObject);
|
|
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
// Bus FDO is initialized
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
|
|
|
RamdiskBusFdo = DeviceObject;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Loop for loader block
|
|
|
|
//
|
|
|
|
if (KeLoaderBlock)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Are we being booted from setup? Not yet supported
|
|
|
|
//
|
|
|
|
ASSERT (!KeLoaderBlock->SetupLdrBlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// All done
|
|
|
|
//
|
|
|
|
DeviceObject->Flags &= DO_DEVICE_INITIALIZING;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Return status
|
|
|
|
//
|
|
|
|
return Status;
|
2008-06-29 02:58:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
|
|
|
IN PUNICODE_STRING RegistryPath)
|
|
|
|
{
|
|
|
|
PCHAR BootDeviceName, CommandLine;
|
2008-07-13 04:23:59 +00:00
|
|
|
PDEVICE_OBJECT PhysicalDeviceObject = NULL;
|
2008-06-29 02:58:05 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Query ramdisk parameters
|
|
|
|
//
|
|
|
|
QueryParameters(RegistryPath);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Save the registry path
|
|
|
|
//
|
|
|
|
DriverRegistryPath = *RegistryPath;
|
|
|
|
DriverRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
RegistryPath->Length +
|
|
|
|
sizeof(WCHAR),
|
|
|
|
TAG('R', 'a', 'm', 'd'));
|
|
|
|
if (!DriverRegistryPath.Buffer) return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyUnicodeString(&DriverRegistryPath, RegistryPath);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set device routines
|
|
|
|
//
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = RamdiskOpenClose;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = RamdiskOpenClose;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = RamdiskReadWrite;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = RamdiskReadWrite;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RamdiskDeviceControl;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = RamdiskPnp;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = RamdiskPower;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = RamdiskSystemControl;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_SCSI] = RamdiskScsi;
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = RamdiskFlushBuffers;
|
|
|
|
DriverObject->DriverExtension->AddDevice = RamdiskAddDevice;
|
|
|
|
DriverObject->DriverUnload = RamdiskUnload;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check for a loader block
|
|
|
|
//
|
|
|
|
if (KeLoaderBlock)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get the boot device name
|
|
|
|
//
|
|
|
|
BootDeviceName = KeLoaderBlock->ArcBootDeviceName;
|
|
|
|
if (BootDeviceName)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if we're booting from ramdisk
|
|
|
|
//
|
|
|
|
if ((strlen(BootDeviceName) >= 10) &&
|
|
|
|
!(_strnicmp(BootDeviceName, "ramdisk(0)", 10)))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We'll have to tell the PnP Manager
|
|
|
|
//
|
|
|
|
ReportDetectedDevice = TRUE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check for a command line
|
|
|
|
//
|
|
|
|
CommandLine = KeLoaderBlock->LoadOptions;
|
|
|
|
if (CommandLine)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Check if this is an ISO boot
|
|
|
|
//
|
|
|
|
if (strstr(CommandLine, "RDEXPORTASCD"))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Remember for later
|
|
|
|
//
|
|
|
|
ExportBootDiskAsCd = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if this is PE boot
|
|
|
|
//
|
|
|
|
if (strstr(CommandLine, "MININT"))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Remember for later
|
|
|
|
//
|
|
|
|
IsWinPEBoot = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Installing from Ramdisk isn't supported yet
|
|
|
|
//
|
2008-07-13 04:23:59 +00:00
|
|
|
ASSERT(!KeLoaderBlock->SetupLdrBlock);
|
2008-06-29 02:58:05 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Are we reporting the device
|
|
|
|
//
|
|
|
|
if (ReportDetectedDevice)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Do it
|
|
|
|
//
|
|
|
|
Status = IoReportDetectedDevice(DriverObject,
|
|
|
|
InterfaceTypeUndefined,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&PhysicalDeviceObject);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
2008-07-13 04:23:59 +00:00
|
|
|
//
|
|
|
|
// ReactOS Fix
|
|
|
|
// The ReactOS Plug and Play Manager is broken and does not create
|
|
|
|
// the required keys when reporting a detected device.
|
|
|
|
// We hack around this ourselves.
|
|
|
|
//
|
2008-07-19 18:44:31 +00:00
|
|
|
RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)
|
|
|
|
PhysicalDeviceObject->DeviceObjectExtension)
|
|
|
|
->DeviceNode->InstancePath,
|
2008-07-13 04:23:59 +00:00
|
|
|
L"Root\\UNKNOWN\\0000");
|
|
|
|
|
2008-06-29 02:58:05 +00:00
|
|
|
//
|
|
|
|
// Create the device object
|
|
|
|
//
|
|
|
|
Status = RamdiskAddDevice(DriverObject, PhysicalDeviceObject);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// We're done
|
|
|
|
//
|
|
|
|
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// Done
|
|
|
|
//
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Done
|
|
|
|
//
|
|
|
|
return Status;
|
|
|
|
}
|