- Seperate the Ramdisk device extension into the Bus Device Extension and the Drive Device Extension.

- Rename the device types to Bus vs Drive, not FDO vs PDO (they're both FDOs).
- Use a common extension (the first 0x60 bytes or so) between Bus and Drive devices.
- Implement first pass of RamdiskCreateDiskDevice -- doesn't create anything, just validates the parameters.
- Implement our delayed work queue for handling requests asynchronously -- SendIrpToThread. Doesn't do anything for now.
- Implement RamdiskQueryDeviceRelations... not sure if we're doing the right thing. According to PnP, we get a warning that we are "misbehaving".
- Driver seems to crash right now, needs fixes.
- Some reformatting to make more lines fit inside 80 characters so it looks nice in joe.


svn path=/trunk/; revision=34589
This commit is contained in:
ReactOS Portable Systems Group 2008-07-19 18:44:31 +00:00
parent aa4af5693a
commit fd5bd1942d

View file

@ -28,8 +28,8 @@
typedef enum _RAMDISK_DEVICE_TYPE typedef enum _RAMDISK_DEVICE_TYPE
{ {
RamdiskFdo, RamdiskBus,
RamdiskPdo RamdiskDrive
} RAMDISK_DEVICE_TYPE; } RAMDISK_DEVICE_TYPE;
typedef enum _RAMDISK_DEVICE_STATE typedef enum _RAMDISK_DEVICE_STATE
@ -40,6 +40,7 @@ typedef enum _RAMDISK_DEVICE_STATE
RamdiskStateStopped, RamdiskStateStopped,
RamdiskStateRemoved, RamdiskStateRemoved,
RamdiskStateBusRemoved, RamdiskStateBusRemoved,
RamdiskStateEnumerated,
} RAMDISK_DEVICE_STATE; } RAMDISK_DEVICE_STATE;
DEFINE_GUID(RamdiskBusInterface, DEFINE_GUID(RamdiskBusInterface,
@ -48,18 +49,29 @@ DEFINE_GUID(RamdiskBusInterface,
0x410F, 0x410F,
0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A); 0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
typedef struct _RAMDISK_EXTENSION //
// 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; \
LIST_ENTRY DiskList;
typedef struct _RAMDISK_BUS_EXTENSION
{ {
RAMDISK_DEVICE_TYPE Type; RAMDISK_EXTENSION;
RAMDISK_DEVICE_STATE State; } RAMDISK_BUS_EXTENSION, *PRAMDISK_BUS_EXTENSION;
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT PhysicalDeviceObject; typedef struct _RAMDISK_DRIVE_EXTENSION
PDEVICE_OBJECT AttachedDevice; {
IO_REMOVE_LOCK RemoveLock; RAMDISK_EXTENSION;
UNICODE_STRING SymbolicLinkName; } RAMDISK_DRIVE_EXTENSION, *PRAMDISK_DRIVE_EXTENSION;
FAST_MUTEX DiskListLock;
LIST_ENTRY DiskListHead;
} RAMDISK_EXTENSION, *PRAMDISK_EXTENSION;
ULONG MaximumViewLength; ULONG MaximumViewLength;
ULONG MaximumPerDiskViewLength; ULONG MaximumPerDiskViewLength;
@ -231,6 +243,49 @@ QueryParameters(IN PUNICODE_STRING RegistryPath)
} }
} }
VOID
NTAPI
RamdiskWorkerThread(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
UNIMPLEMENTED;
while (TRUE);
}
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 NTSTATUS
NTAPI NTAPI
RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject, RamdiskOpenClose(IN PDEVICE_OBJECT DeviceObject,
@ -257,11 +312,73 @@ RamdiskReadWrite(IN PDEVICE_OBJECT DeviceObject,
NTSTATUS NTSTATUS
NTAPI NTAPI
RamdiskCreateDiskDevice(IN PRAMDISK_EXTENSION DeviceExtension, RamdiskCreateDiskDevice(IN PRAMDISK_BUS_EXTENSION DeviceExtension,
IN PRAMDISK_CREATE_INPUT Input, IN PRAMDISK_CREATE_INPUT Input,
IN BOOLEAN ValidateOnly, IN BOOLEAN ValidateOnly,
OUT PDEVICE_OBJECT *DeviceObject) OUT PDEVICE_OBJECT *DeviceObject)
{ {
ULONG BasePage, ViewCount, DiskType;
//
// 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;
//
// FIXME-TODO: Implement the rest of the code
//
}
UNIMPLEMENTED; UNIMPLEMENTED;
while (TRUE); while (TRUE);
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -275,7 +392,7 @@ RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
{ {
PRAMDISK_CREATE_INPUT Input; PRAMDISK_CREATE_INPUT Input;
ULONG Length; ULONG Length;
PRAMDISK_EXTENSION DeviceExtension; PRAMDISK_BUS_EXTENSION DeviceExtension;
ULONG DiskType; ULONG DiskType;
PWCHAR FileNameStart, FileNameEnd; PWCHAR FileNameStart, FileNameEnd;
NTSTATUS Status; NTSTATUS Status;
@ -284,7 +401,7 @@ RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
// //
// Get the device extension and our input data // Get the device extension and our input data
// //
DeviceExtension = (PRAMDISK_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; Length = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer; Input = (PRAMDISK_CREATE_INPUT)Irp->AssociatedIrp.SystemBuffer;
@ -326,7 +443,8 @@ RamdiskCreateRamdisk(IN PDEVICE_OBJECT DeviceObject,
// //
// Validate the disk type // Validate the disk type
// //
if ((Input->Options.ExportAsCd) && (DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM)) if ((Input->Options.ExportAsCd) &&
(DiskType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
{ {
// //
// If the type isn't CDFS, it has to at least be raw CD // If the type isn't CDFS, it has to at least be raw CD
@ -377,7 +495,7 @@ RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
{ {
NTSTATUS Status; NTSTATUS Status;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
PRAMDISK_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PRAMDISK_BUS_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
ULONG Information = 0; ULONG Information = 0;
// //
@ -396,9 +514,9 @@ RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
} }
// //
// Check if this is an FDO or PDO // Check if this is an bus device or the drive
// //
if (DeviceExtension->Type == RamdiskFdo) if (DeviceExtension->Type == RamdiskBus)
{ {
// //
// Check what the request is // Check what the request is
@ -429,7 +547,7 @@ RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
else else
{ {
// //
// PDO code not yet done // Drive code not yet done
// //
ASSERT(FALSE); ASSERT(FALSE);
} }
@ -437,8 +555,7 @@ RamdiskDeviceControl(IN PDEVICE_OBJECT DeviceObject,
// //
// Queue the request to our worker thread // Queue the request to our worker thread
// //
UNIMPLEMENTED; Status = SendIrpToThread(DeviceObject, Irp);
while (TRUE);
CompleteRequest: CompleteRequest:
// //
@ -461,13 +578,213 @@ CompleteRequest:
return Status; return Status;
} }
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));
}
//
// 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);
}
NTSTATUS NTSTATUS
NTAPI NTAPI
RamdiskPnp(IN PDEVICE_OBJECT DeviceObject, RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp) IN PIRP Irp)
{ {
PIO_STACK_LOCATION IoStackLocation; PIO_STACK_LOCATION IoStackLocation;
PRAMDISK_EXTENSION DeviceExtension; PRAMDISK_BUS_EXTENSION DeviceExtension;
NTSTATUS Status; NTSTATUS Status;
UCHAR Minor; UCHAR Minor;
@ -569,9 +886,9 @@ RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
case IRP_MN_QUERY_ID: case IRP_MN_QUERY_ID:
// //
// Are we a PDO? // Are we a drive?
// //
if (DeviceExtension->Type == RamdiskPdo) if (DeviceExtension->Type == RamdiskDrive)
{ {
DPRINT1("PnP IRP: %lx\n", Minor); DPRINT1("PnP IRP: %lx\n", Minor);
while (TRUE); while (TRUE);
@ -581,9 +898,9 @@ RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
case IRP_MN_QUERY_BUS_INFORMATION: case IRP_MN_QUERY_BUS_INFORMATION:
// //
// Are we a PDO? // Are we a drive?
// //
if (DeviceExtension->Type == RamdiskPdo) if (DeviceExtension->Type == RamdiskDrive)
{ {
DPRINT1("PnP IRP: %lx\n", Minor); DPRINT1("PnP IRP: %lx\n", Minor);
while (TRUE); while (TRUE);
@ -599,9 +916,9 @@ RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
case IRP_MN_QUERY_DEVICE_TEXT: case IRP_MN_QUERY_DEVICE_TEXT:
// //
// Are we a PDO? // Are we a drive?
// //
if (DeviceExtension->Type == RamdiskPdo) if (DeviceExtension->Type == RamdiskDrive)
{ {
DPRINT1("PnP IRP: %lx\n", Minor); DPRINT1("PnP IRP: %lx\n", Minor);
while (TRUE); while (TRUE);
@ -610,16 +927,22 @@ RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
case IRP_MN_QUERY_DEVICE_RELATIONS: case IRP_MN_QUERY_DEVICE_RELATIONS:
DPRINT1("PnP IRP: %lx\n", Minor); //
while (TRUE); // Call our main routine
break; //
Status = RamdiskQueryDeviceRelations(IoStackLocation->
Parameters.
QueryDeviceRelations.Type,
DeviceObject,
Irp);
goto ReleaseAndReturn;
case IRP_MN_QUERY_CAPABILITIES: case IRP_MN_QUERY_CAPABILITIES:
// //
// Are we a PDO? // Are we a drive?
// //
if (DeviceExtension->Type == RamdiskPdo) if (DeviceExtension->Type == RamdiskDrive)
{ {
DPRINT1("PnP IRP: %lx\n", Minor); DPRINT1("PnP IRP: %lx\n", Minor);
while (TRUE); while (TRUE);
@ -642,9 +965,9 @@ RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
} }
// //
// Are we an FDO? // Are we the bus?
// //
if (DeviceExtension->Type == RamdiskFdo) if (DeviceExtension->Type == RamdiskBus)
{ {
// //
// Do we have an attached device? // Do we have an attached device?
@ -720,23 +1043,23 @@ NTAPI
RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject, RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject) IN PDEVICE_OBJECT PhysicalDeviceObject)
{ {
PRAMDISK_EXTENSION DeviceExtension; PRAMDISK_BUS_EXTENSION DeviceExtension;
PDEVICE_OBJECT AttachedDevice; PDEVICE_OBJECT AttachedDevice;
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING DeviceName; UNICODE_STRING DeviceName;
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
// //
// Only create the FDO once // Only create the bus FDO once
// //
if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED; if (RamdiskBusFdo) return STATUS_DEVICE_ALREADY_ATTACHED;
// //
// Create the FDO // Create the bus FDO
// //
RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk"); RtlInitUnicodeString(&DeviceName, L"\\Device\\Ramdisk");
Status = IoCreateDevice(DriverObject, Status = IoCreateDevice(DriverObject,
sizeof(RAMDISK_EXTENSION), sizeof(RAMDISK_BUS_EXTENSION),
&DeviceName, &DeviceName,
FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN, FILE_DEVICE_SECURE_OPEN,
@ -745,26 +1068,27 @@ RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
// //
// Initialize the FDO extension // Initialize the bus FDO extension
// //
DeviceExtension = (PRAMDISK_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceObject->DeviceExtension, sizeof(RAMDISK_EXTENSION)); RtlZeroMemory(DeviceObject->DeviceExtension,
sizeof(RAMDISK_BUS_EXTENSION));
// //
// Set FDO flags // Set bus FDO flags
// //
DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO; DeviceObject->Flags |= DO_POWER_PAGABLE | DO_DIRECT_IO;
// //
// Setup the FDO extension // Setup the bus FDO extension
// //
DeviceExtension->Type = RamdiskFdo; DeviceExtension->Type = RamdiskBus;
ExInitializeFastMutex(&DeviceExtension->DiskListLock); ExInitializeFastMutex(&DeviceExtension->DiskListLock);
IoInitializeRemoveLock(&DeviceExtension->RemoveLock, IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
TAG('R', 'a', 'm', 'd'), TAG('R', 'a', 'm', 'd'),
0, 0,
1); 1);
InitializeListHead(&DeviceExtension->DiskListHead); InitializeListHead(&DeviceExtension->DiskList);
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
DeviceExtension->DeviceObject = DeviceObject; DeviceExtension->DeviceObject = DeviceObject;
@ -802,7 +1126,7 @@ RamdiskAddDevice(IN PDRIVER_OBJECT DriverObject,
} }
// //
// FDO is initialized // Bus FDO is initialized
// //
RamdiskBusFdo = DeviceObject; RamdiskBusFdo = DeviceObject;
@ -955,7 +1279,9 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
// the required keys when reporting a detected device. // the required keys when reporting a detected device.
// We hack around this ourselves. // We hack around this ourselves.
// //
RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath, RtlCreateUnicodeString(&((PEXTENDED_DEVOBJ_EXTENSION)
PhysicalDeviceObject->DeviceObjectExtension)
->DeviceNode->InstancePath,
L"Root\\UNKNOWN\\0000"); L"Root\\UNKNOWN\\0000");
// //