[FLOPPY] Make floppy drives letters being handled by the MountMgr

This involves many changes/fixes in the floppy driver:
- Stop creating ourselves our DOS device, it's up to the MountMgr or to the kernel;
- Report each new floppy drive to the MountMgr (this is a hack for now);
- As a consequence, stop storing the symlink name into the DRIVE_INFO structure;
- Store the device name instead;
- On IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, don't return DOS device, but device name;
- On IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, properly return if buffer is way too small;
- Hackplement IOCTL_MOUNTDEV_QUERY_UNIQUE_ID so that it returns device name.
This commit is contained in:
Pierre Schweitzer 2019-10-27 11:35:23 +01:00
parent e133817811
commit 6889cff5b5
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
3 changed files with 143 additions and 35 deletions

View file

@ -406,9 +406,6 @@ Unload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING Link;
RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
IoDeleteSymbolicLink(&Link);
RtlInitUnicodeString(&Link, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
IoDeassignArcName(&Link);
@ -811,6 +808,98 @@ InitController(PCONTROLLER_INFO ControllerInfo)
}
static VOID NTAPI
ReportToMountMgr(UCHAR ControlerId, UCHAR DriveId)
/*
* FUNCTION: Called to report a new controler to the MountMgr
* ARGUMENTS:
* ControlerId: ID of the controler
* DriveId: ID of the device for the controler
* RETURNS:
* Nothing
* NOTES:
* - This is a hack to allow MountMgr handling our devices
*/
{
NTSTATUS Status;
UNICODE_STRING MountMgrDevice;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PMOUNTMGR_TARGET_NAME MountTarget;
ULONG DeviceLen;
PIRP Irp;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
/* First, get MountMgr DeviceObject */
RtlInitUnicodeString(&MountMgrDevice, MOUNTMGR_DEVICE_NAME);
Status = IoGetDeviceObjectPointer(&MountMgrDevice, FILE_READ_ATTRIBUTES,
&FileObject, &DeviceObject);
if(!NT_SUCCESS(Status))
{
WARN_(FLOPPY, "ReportToMountMgr: Can't get MountMgr pointers %lx\n", Status);
return;
}
DeviceLen = wcslen(&gControllerInfo[ControlerId].DriveInfo[DriveId].DeviceNameBuffer[0]) * sizeof(WCHAR);
/* Allocate input buffer to report our floppy device */
MountTarget = ExAllocatePool(NonPagedPool,
sizeof(MOUNTMGR_TARGET_NAME) + DeviceLen);
if(!MountTarget)
{
WARN_(FLOPPY, "ReportToMountMgr: Allocation of mountTarget failed\n");
ObDereferenceObject(FileObject);
return;
}
MountTarget->DeviceNameLength = DeviceLen;
RtlCopyMemory(MountTarget->DeviceName,
gControllerInfo[ControlerId].DriveInfo[DriveId].DeviceNameBuffer,
DeviceLen);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Build the IRP used to communicate with the MountMgr */
Irp = IoBuildDeviceIoControlRequest(IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
DeviceObject,
MountTarget,
sizeof(MOUNTMGR_TARGET_NAME) + DeviceLen,
NULL,
0,
FALSE,
&Event,
&IoStatus);
if(!Irp)
{
WARN_(FLOPPY, "ReportToMountMgr: Allocation of irp failed\n");
ExFreePool(MountTarget);
ObDereferenceObject(FileObject);
return;
}
/* Call the MountMgr */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
/* We're done */
INFO_(FLOPPY, "Reported to the MountMgr: %lx\n", Status);
ExFreePool(MountTarget);
ObDereferenceObject(FileObject);
return;
}
static BOOLEAN NTAPI
AddControllers(PDRIVER_OBJECT DriverObject)
/*
@ -912,9 +1001,7 @@ AddControllers(PDRIVER_OBJECT DriverObject)
/* 3: per-drive setup */
for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
{
WCHAR DeviceNameBuf[MAX_DEVICE_NAME];
UNICODE_STRING DeviceName;
UNICODE_STRING LinkName;
UNICODE_STRING ArcPath;
UCHAR DriveNumber;
@ -936,9 +1023,8 @@ AddControllers(PDRIVER_OBJECT DriverObject)
DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */
RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR));
swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber);
RtlInitUnicodeString(&DeviceName, DeviceNameBuf);
swprintf(gControllerInfo[i].DriveInfo[j].DeviceNameBuffer, L"\\Device\\Floppy%d", DriveNumber);
RtlInitUnicodeString(&DeviceName, gControllerInfo[i].DriveInfo[j].DeviceNameBuffer);
if(IoCreateDevice(DriverObject, sizeof(PVOID), &DeviceName,
FILE_DEVICE_DISK, FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, FALSE,
@ -949,7 +1035,9 @@ AddControllers(PDRIVER_OBJECT DriverObject)
continue; /* continue on to next drive */
}
INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject);
INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n",
gControllerInfo[i].DriveInfo[j].DeviceNameBuffer,
gControllerInfo[i].DriveInfo[j].DeviceObject);
/* 3b.5: Create an ARC path in case we're booting from this drive */
swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer,
@ -961,38 +1049,30 @@ AddControllers(PDRIVER_OBJECT DriverObject)
/* 3c: Set flags up */
gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO;
/* 3d: Create a symlink */
swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A');
RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
if(IoCreateSymbolicLink(&LinkName, &DeviceName) != STATUS_SUCCESS)
{
WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber);
IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
IoDeassignArcName(&ArcPath);
continue; /* continue to next drive */
}
/* 3e: Increase global floppy drives count */
/* 3d: Increase global floppy drives count */
IoGetConfigurationInformation()->FloppyCount++;
/* 3f: Set up the DPC */
/* 3e: Set up the DPC */
IoInitializeDpcRequest(gControllerInfo[i].DriveInfo[j].DeviceObject, (PIO_DPC_ROUTINE)DpcForIsr);
/* 3g: Point the device extension at our DriveInfo struct */
/* 3f: Point the device extension at our DriveInfo struct */
gControllerInfo[i].DriveInfo[j].DeviceObject->DeviceExtension = &gControllerInfo[i].DriveInfo[j];
/* 3h: neat comic strip */
/* 3g: neat comic strip */
/* 3i: set the initial media type to unknown */
/* 3h: set the initial media type to unknown */
memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY));
gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown;
/* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */
/* 3i: Now that we're done, set the Initialized flag so we know to free this in Unload */
gControllerInfo[i].DriveInfo[j].Initialized = TRUE;
/* 3k: Clear the DO_DEVICE_INITIALIZING flag */
/* 3j: Clear the DO_DEVICE_INITIALIZING flag */
gControllerInfo[i].DriveInfo[j].DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
/* 3k: Report to the MountMgr */
ReportToMountMgr(i, j);
/* 3l: Attempt to get drive info - if a floppy is already present */
StartMotor(&gControllerInfo[i].DriveInfo[j]);
RWDetermineMediaType(&gControllerInfo[i].DriveInfo[j], TRUE);

View file

@ -48,8 +48,8 @@ typedef struct _DRIVE_INFO
CM_FLOPPY_DEVICE_DATA FloppyDeviceData;
DISK_GEOMETRY DiskGeometry;
UCHAR BytesPerSectorCode;
WCHAR SymLinkBuffer[MAX_DEVICE_NAME];
WCHAR ArcPathBuffer[MAX_ARC_PATH_LEN];
WCHAR DeviceNameBuffer[MAX_DEVICE_NAME];
ULONG DiskChangeCount;
BOOLEAN Initialized;
} DRIVE_INFO, *PDRIVE_INFO;

View file

@ -75,6 +75,7 @@ DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
ULONG Code = Stack->Parameters.DeviceIoControl.IoControlCode;
BOOLEAN DiskChanged;
PMOUNTDEV_NAME Name;
PMOUNTDEV_UNIQUE_ID UniqueId;
TRACE_(FLOPPY, "DeviceIoctl called\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
@ -256,27 +257,54 @@ DeviceIoctlPassive(PDRIVE_INFO DriveInfo, PIRP Irp)
Irp->IoStatus.Information = 0;
break;
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
if (OutputLength < sizeof(MOUNTDEV_NAME)) {
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
if(OutputLength < sizeof(MOUNTDEV_UNIQUE_ID))
{
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
Irp->IoStatus.Information = 0;
break;
}
UniqueId = Irp->AssociatedIrp.SystemBuffer;
UniqueId->UniqueIdLength = wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
if(OutputLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength)
{
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
break;
}
RtlCopyMemory(UniqueId->UniqueId, &DriveInfo->DeviceNameBuffer[0],
UniqueId->UniqueIdLength);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueId->UniqueIdLength;
break;
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
if(OutputLength < sizeof(MOUNTDEV_NAME))
{
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
Name = Irp->AssociatedIrp.SystemBuffer;
Name->NameLength = wcslen(&DriveInfo->SymLinkBuffer[0]) * sizeof(WCHAR);
Name->NameLength = wcslen(&DriveInfo->DeviceNameBuffer[0]) * sizeof(WCHAR);
if (OutputLength < sizeof(USHORT) + Name->NameLength) {
if(OutputLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength)
{
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
break;
}
RtlCopyMemory(Name->Name, &DriveInfo->SymLinkBuffer[0],
RtlCopyMemory(Name->Name, &DriveInfo->DeviceNameBuffer[0],
Name->NameLength);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(USHORT) + Name->NameLength;
Irp->IoStatus.Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + Name->NameLength;
break;
default: