0x410F,
0x80, 0xE4, 0x05, 0xF8, 0x10, 0xE7, 0xA8, 0x8A);
+DEFINE_GUID(RamdiskDiskInterface,
+ 0x31D909F0,
+ 0x2CDF,
+ 0x4A20,
+ 0x9E, 0xD4, 0x7D, 0x65, 0x47, 0x6C, 0xA7, 0x68);
+
typedef struct _RAMDISK_EXTENSION
{
RAMDISK_DEVICE_TYPE Type;
ExInitializeFastMutex(&DriveExtension->DiskListLock);
IoInitializeRemoveLock(&DriveExtension->RemoveLock,
'dmaR',
- 0,
- 1);
+ 1,
+ 0);
DriveExtension->DriveDeviceName = DeviceName;
DriveExtension->SymbolicLinkName = SymbolicLinkName;
DriveExtension->GuidString = GuidString;
//
// Anything but bus relations, we don't handle
//
- if (Type) goto PassToNext;
+ if (Type != BusRelations) goto PassToNext;
//
// Acquire the disk list lock
return Status;
}
+NTSTATUS
+NTAPI
+RamdiskQueryId(IN PRAMDISK_DRIVE_EXTENSION DriveExtension,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStackLocation;
+ PWSTR OutputString = NULL;
+ ULONG StringLength;
+
+ Status = STATUS_SUCCESS;
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+ //
+ // Get what is being queried
+ //
+ switch (IoStackLocation->Parameters.QueryId.IdType)
+ {
+ case BusQueryDeviceID:
+
+ //
+ // Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
+ // In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
+ // chars to store Ramdisk\RamVolume instead
+ //
+ StringLength = 4 * (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK) + sizeof(L"Ramdisk\\RamDisk");
+ OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, L"Ramdisk\\", StringLength / sizeof(WCHAR));
+ if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
+ {
+ wcsncat(OutputString, L"RamVolume", StringLength / sizeof(WCHAR));
+ }
+ else
+ {
+ wcsncat(OutputString, L"RamDisk", StringLength / sizeof(WCHAR));
+ }
+
+ break;
+
+ case BusQueryHardwareIDs:
+
+ //
+ // Allocate a buffer long enough to receive Ramdisk\RamDisk in any case
+ // In case we don't have RAMDISK_REGISTRY_DISK, we then need two more
+ // chars to store Ramdisk\RamVolume instead
+ // We also need an extra char, because it is required that the string
+ // is null-terminated twice
+ //
+ StringLength = 4 * (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK) +
+ sizeof(UNICODE_NULL) + sizeof(L"Ramdisk\\RamDisk");
+ OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, L"Ramdisk\\", StringLength / sizeof(WCHAR));
+ if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
+ {
+ wcsncat(OutputString, L"RamVolume", StringLength / sizeof(WCHAR));
+ }
+ else
+ {
+ wcsncat(OutputString, L"RamDisk", StringLength / sizeof(WCHAR));
+ }
+ OutputString[(StringLength / sizeof(WCHAR)) - 1] = UNICODE_NULL;
+
+ break;
+
+ case BusQueryCompatibleIDs:
+
+ if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
+ {
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ StringLength = sizeof(L"GenDisk");
+ OutputString = ExAllocatePoolWithTag(PagedPool, StringLength, 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, L"GenDisk", StringLength / sizeof(WCHAR));
+ OutputString[(StringLength / sizeof(WCHAR)) - 1] = UNICODE_NULL;
+
+ break;
+
+ case BusQueryInstanceID:
+
+ OutputString = ExAllocatePoolWithTag(PagedPool, DriveExtension->GuidString.MaximumLength, 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, DriveExtension->GuidString.Buffer, DriveExtension->GuidString.MaximumLength / sizeof(WCHAR));
+
+ break;
+
+ case BusQueryDeviceSerialNumber:
+
+ //
+ // Nothing to do
+ //
+
+ break;
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = (ULONG_PTR)OutputString;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+RamdiskQueryCapabilities(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStackLocation;
+ PDEVICE_CAPABILITIES DeviceCapabilities;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension;
+
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceCapabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;
+ DriveExtension = DeviceObject->DeviceExtension;
+
+ //
+ // Validate our input buffer
+ //
+ if (DeviceCapabilities->Version != 1 || DeviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ //
+ // And set everything we know about our capabilities
+ //
+ DeviceCapabilities->Removable = MarkRamdisksAsRemovable;
+ DeviceCapabilities->UniqueID = TRUE;
+ DeviceCapabilities->SilentInstall = TRUE;
+ DeviceCapabilities->RawDeviceOK = TRUE;
+ DeviceCapabilities->SurpriseRemovalOK = (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK);
+ DeviceCapabilities->NoDisplayInUI = TRUE;
+ Status = STATUS_SUCCESS;
+ }
+
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+RamdiskQueryDeviceText(IN PRAMDISK_DRIVE_EXTENSION DriveExtension,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStackLocation;
+ DEVICE_TEXT_TYPE DeviceTextType;
+ PWSTR OutputString = NULL;
+
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceTextType = IoStackLocation->Parameters.QueryDeviceText.DeviceTextType;
+ Status = STATUS_SUCCESS;
+
+ //
+ // Just copy our constants, according to the input
+ //
+ switch (DeviceTextType)
+ {
+ case DeviceTextDescription:
+
+ OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk"), 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, L"RamDisk", sizeof(L"RamDisk") / sizeof(WCHAR));
+
+ break;
+
+ case DeviceTextLocationInformation:
+
+ OutputString = ExAllocatePoolWithTag(PagedPool, sizeof(L"RamDisk\\0"), 'dmaR');
+ if (OutputString == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ wcsncpy(OutputString, L"RamDisk\\0", sizeof(L"RamDisk\\0") / sizeof(WCHAR));
+
+ break;
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = (ULONG_PTR)OutputString;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+RamdiskQueryBusInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PPNP_BUS_INFORMATION PnpBusInfo;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ //
+ // Allocate output memory
+ //
+ PnpBusInfo = ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), 'dmaR');
+ if (PnpBusInfo == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ //
+ // Copy our bus GUID and set our legacy type
+ //
+ RtlCopyMemory(&PnpBusInfo->BusTypeGuid, &GUID_BUS_TYPE_RAMDISK, sizeof(GUID));
+ PnpBusInfo->LegacyBusType = PNPBus;
+ PnpBusInfo->BusNumber = 0;
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = (ULONG_PTR)PnpBusInfo;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+RamdiskIoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+
+{
+ //
+ // Just set the event to unlock caller
+ //
+ KeSetEvent((PKEVENT)Context, 0, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
NTSTATUS
NTAPI
RamdiskPnp(IN PDEVICE_OBJECT DeviceObject,
PRAMDISK_BUS_EXTENSION DeviceExtension;
NTSTATUS Status;
UCHAR Minor;
-
+ KEVENT Event;
+
//
// Get the device extension and stack location
//
switch (Minor)
{
case IRP_MN_START_DEVICE:
-
- UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
+
+ if (DeviceExtension->Type == RamdiskDrive)
+ {
+ ULONG ResultLength;
+ DEVICE_INSTALL_STATE InstallState;
+ PRAMDISK_DRIVE_EXTENSION DriveExtension = (PRAMDISK_DRIVE_EXTENSION)DeviceExtension;
+
+ //
+ // If we already have a drive name, free it
+ //
+ if (DriveExtension->DriveDeviceName.Buffer)
+ {
+ ExFreePool(DriveExtension->DriveDeviceName.Buffer);
+ }
+
+ //
+ // Register our device interface
+ //
+ if (DriveExtension->DiskType != RAMDISK_REGISTRY_DISK)
+ {
+ Status = IoRegisterDeviceInterface(DeviceObject,
+ &GUID_DEVINTERFACE_VOLUME,
+ NULL,
+ &DriveExtension->DriveDeviceName);
+ }
+ else
+ {
+ Status = IoRegisterDeviceInterface(DeviceObject,
+ &RamdiskDiskInterface,
+ NULL,
+ &DriveExtension->DriveDeviceName);
+ }
+
+ //
+ // If we were asked not to assign a drive letter or
+ // if getting a name failed, just return saying
+ // we're now started
+ //
+ if (DriveExtension->DiskOptions.NoDriveLetter ||
+ DriveExtension->DriveDeviceName.Buffer == NULL)
+ {
+ DriveExtension->State = RamdiskStateStarted;
+ Irp->IoStatus.Status = Status;
+ break;
+ }
+
+ //
+ // Now get our installation state
+ //
+ Status = IoGetDeviceProperty(DeviceObject, DevicePropertyInstallState,
+ sizeof(InstallState), &InstallState, &ResultLength);
+ //
+ // If querying the information failed, assume success
+ //
+ if (!NT_SUCCESS(Status))
+ {
+ InstallState = InstallStateInstalled;
+ }
+
+ //
+ // If we were properly installed, then, enable the interface
+ //
+ if (InstallState == InstallStateInstalled)
+ {
+ Status = IoSetDeviceInterfaceState(&DriveExtension->DriveDeviceName, TRUE);
+ }
+
+ //
+ // We're fine & up
+ //
+ DriveExtension->State = RamdiskStateStarted;
+ Irp->IoStatus.Status = Status;
+ break;
+ }
+
+ //
+ // Prepare next stack to pass it down
+ //
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+
+ //
+ // Initialize our notification event & our completion routine
+ //
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ IoSetCompletionRoutine(Irp, RamdiskIoCompletionRoutine, &Event, TRUE, TRUE, TRUE);
+
+ //
+ // Call lower driver
+ //
+ Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ //
+ // If it succeed to start, then, enable ourselve and we're up!
+ //
+ if (NT_SUCCESS(Status))
+ {
+ Status = IoSetDeviceInterfaceState(&DeviceExtension->DriveDeviceName, TRUE);
+ DeviceExtension->State = RamdiskStateStarted;
+ }
+
+ Irp->IoStatus.Status = Status;
break;
case IRP_MN_QUERY_STOP_DEVICE:
//
if (DeviceExtension->Type == RamdiskDrive)
{
- UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
+ Status = RamdiskQueryId((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp);
}
break;
//
if (DeviceExtension->Type == RamdiskDrive)
{
- UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
+ Status = RamdiskQueryBusInformation(DeviceObject, Irp);
}
break;
//
if (DeviceExtension->Type == RamdiskDrive)
{
- UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
+ Status = RamdiskQueryDeviceText((PRAMDISK_DRIVE_EXTENSION)DeviceExtension, Irp);
}
break;
//
if (DeviceExtension->Type == RamdiskDrive)
{
- UNIMPLEMENTED_DBGBREAK("PnP IRP: %lx\n", Minor);
+ Status = RamdiskQueryCapabilities(DeviceObject, Irp);
}
break;
ExInitializeFastMutex(&DeviceExtension->DiskListLock);
IoInitializeRemoveLock(&DeviceExtension->RemoveLock,
'dmaR',
- 0,
- 1);
+ 1,
+ 0);
InitializeListHead(&DeviceExtension->DiskList);
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
DeviceExtension->DeviceObject = DeviceObject;