[CLASS2] Drop the drive letter hack

This commit is contained in:
Pierre Schweitzer 2019-11-11 18:18:12 +01:00
parent 2b39b42a0a
commit 887200703c
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B

View file

@ -13,10 +13,6 @@
#include <include/class2.h>
#include <stdio.h>
/* Part of the drive letter hack */
#include <ntifs.h>
#include <ketypes.h>
//#define NDEBUG
#include <debug.h>
@ -135,315 +131,28 @@ DriverEntry(
return STATUS_SUCCESS;
}
/* The following hack to assign drive letters with a non-PnP storage stack */
typedef struct _CLASS_DEVICE_INFO {
ULONG Signature;
ULONG DeviceType;
ULONG Partitions;
ULONG DeviceNumber;
ULONG DriveNumber;
PDEVICE_OBJECT LowerDevice;
} CLASS_DEVICE_INFO, *PCLASS_DEVICE_INFO;
typedef struct _CLASS_DRIVER_EXTENSION {
ULONG PortNumber;
UNICODE_STRING RegistryPath;
CLASS_INIT_DATA InitializationData;
} CLASS_DRIVER_EXTENSION, *PCLASS_DRIVER_EXTENSION;
VOID
NTAPI
ScsiClassRemoveDriveLetter(PCLASS_DEVICE_INFO DeviceInfo)
{
WCHAR Buffer1[100];
UNICODE_STRING DriveLetterU;
ULONG Index;
DriveLetterU.Buffer = Buffer1;
DriveLetterU.MaximumLength = sizeof(Buffer1);
/* Delete the symbolic link to PhysicalDriveX */
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DeviceInfo->DriveNumber) * sizeof(WCHAR);
IoDeleteSymbolicLink(&DriveLetterU);
DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU);
for (Index = 0; Index < sizeof(ULONG) * 8; Index++)
{
if (DeviceInfo->Partitions & (1 << Index))
{
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR);
IoDeleteSymbolicLink(&DriveLetterU);
DbgPrint("HACK: Deleted symbolic link %wZ\n", &DriveLetterU);
}
}
}
NTSTATUS
NTAPI
ScsiClassAssignDriveLetter(PCLASS_DEVICE_INFO DeviceInfo)
{
WCHAR Buffer1[100];
WCHAR Buffer2[100];
UNICODE_STRING DriveLetterU, PartitionU;
NTSTATUS Status;
ULONG Index, PartitionNumber, DeviceNumber, DriveNumber;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK Iosb;
HANDLE PartitionHandle;
/* We assume this device does not current have a drive letter */
Index = 0;
DeviceNumber = 0;
DriveNumber = 0;
PartitionNumber = 1;
DriveLetterU.Buffer = Buffer1;
DriveLetterU.MaximumLength = sizeof(Buffer1);
PartitionU.Buffer = Buffer2;
PartitionU.MaximumLength = sizeof(Buffer2);
/* Determine the correct disk number */
do
{
/* Check that the disk exists */
if (DeviceInfo->DeviceType == FILE_DEVICE_DISK)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\HardDisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR);
}
else if (DeviceInfo->DeviceType == FILE_DEVICE_CD_ROM)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\CdRom%d", DeviceNumber) * sizeof(WCHAR);
}
InitializeObjectAttributes(&ObjectAttributes,
&PartitionU,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwOpenFile(&PartitionHandle,
FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&Iosb,
0,
0);
if (!NT_SUCCESS(Status))
{
/* Return the last one that worked */
DeviceNumber--;
}
else
{
ZwClose(PartitionHandle);
DeviceNumber++;
}
} while (Status == STATUS_SUCCESS);
/* Determine the correct drive number */
do
{
/* Check that the drive exists */
if (DeviceInfo->DeviceType == FILE_DEVICE_DISK)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR);
}
else if (DeviceInfo->DeviceType == FILE_DEVICE_CD_ROM)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\??\\%C:", ('C' + DriveNumber)) * sizeof(WCHAR);
}
InitializeObjectAttributes(&ObjectAttributes,
&PartitionU,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwOpenFile(&PartitionHandle,
FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&Iosb,
0,
0);
if (NT_SUCCESS(Status))
{
ZwClose(PartitionHandle);
DriveNumber++;
}
} while (Status == STATUS_SUCCESS);
if (DeviceInfo->DeviceType == FILE_DEVICE_DISK)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR);
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR);
}
else if (DeviceInfo->DeviceType == FILE_DEVICE_CD_ROM)
{
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\CdRom%d", DeviceNumber) * sizeof(WCHAR);
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + DriveNumber)) * sizeof(WCHAR);
}
/* Create the symbolic link to PhysicalDriveX */
Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU);
if (!NT_SUCCESS(Status))
{
/* Failed to create symbolic link */
DbgPrint("Failed to create symbolic link %wZ -> %wZ with %lx\n", &PartitionU, &DriveLetterU, Status);
return Status;
}
DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU);
DeviceInfo->DeviceNumber = DeviceNumber;
DeviceInfo->DriveNumber = DriveNumber;
if (DeviceInfo->DeviceType == FILE_DEVICE_CD_ROM)
{
/* done for cdroms */
return STATUS_SUCCESS;
}
while (TRUE)
{
/* Check that the disk exists */
PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition%d", DeviceNumber, PartitionNumber) * sizeof(WCHAR);
InitializeObjectAttributes(&ObjectAttributes,
&PartitionU,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwOpenFile(&PartitionHandle,
FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&Iosb,
0,
0);
if (!NT_SUCCESS(Status))
break;
else
{
ZwClose(PartitionHandle);
/* Assign it a drive letter */
do
{
DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\%C:", ('C' + Index)) * sizeof(WCHAR);
Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU);
Index++;
} while (Status != STATUS_SUCCESS);
DeviceInfo->Partitions |= (1 << (Index - 1));
DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU);
PartitionNumber++;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
ScsiClassPlugPlay(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCLASS_DEVICE_INFO DeviceInfo = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (IrpSp->MinorFunction == IRP_MN_START_DEVICE)
{
ASSERT(DeviceInfo->Signature == '2slc');
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceInfo->LowerDevice, Irp);
}
else if (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)
{
ASSERT(DeviceInfo->Signature == '2slc');
ScsiClassRemoveDriveLetter(DeviceInfo);
IoForwardIrpSynchronously(DeviceInfo->LowerDevice, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoDetachDevice(DeviceInfo->LowerDevice);
IoDeleteDevice(DeviceObject);
return STATUS_SUCCESS;
}
else
{
if (DeviceInfo->Signature == '2slc')
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceInfo->LowerDevice, Irp);
}
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
}
NTSTATUS
NTAPI
ScsiClassAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
PCLASS_DRIVER_EXTENSION DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
PCLASS_DEVICE_INFO DeviceInfo;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
if (DriverExtension->InitializationData.ClassFindDevices(DriverObject, &DriverExtension->RegistryPath, &DriverExtension->InitializationData,
PhysicalDeviceObject, DriverExtension->PortNumber))
{
/* Create a device object */
Status = IoCreateDevice(DriverObject,
sizeof(CLASS_DEVICE_INFO),
NULL,
DriverExtension->InitializationData.DeviceType,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status))
{
return Status;
}
DeviceInfo = DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceInfo, sizeof(CLASS_DEVICE_INFO));
DeviceInfo->Signature = '2slc';
/* Attach it to the PDO */
DeviceInfo->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
DeviceInfo->DeviceType = DriverExtension->InitializationData.DeviceType;
/* Check that the kernel has already assigned drive letters */
if (KeLoaderBlock == NULL)
{
/* Assign a drive letter */
ScsiClassAssignDriveLetter(DeviceInfo);
}
else
{
/* The kernel will handle it */
}
/* Move to the next port number */
DriverExtension->PortNumber++;
}
else
{
/* Failed to find device */
DbgPrint("FAILED TO FIND DEVICE!\n");
}
return STATUS_SUCCESS;
}
/* ---- End hack ---- */
ULONG
@ -477,15 +186,14 @@ Return Value:
PDRIVER_OBJECT DriverObject = Argument1;
ULONG portNumber = 0;
PDEVICE_OBJECT portDeviceObject;
NTSTATUS status;
STRING deviceNameString;
UNICODE_STRING unicodeDeviceName;
PFILE_OBJECT fileObject;
CCHAR deviceNameBuffer[256];
/* BOOLEAN deviceFound = FALSE; See note at the end */
PCLASS_DRIVER_EXTENSION DriverExtension;
PUNICODE_STRING RegistryPath = Argument2;
BOOLEAN deviceFound = FALSE;
DebugPrint((3,"\n\nSCSI Class Driver\n"));
@ -516,27 +224,6 @@ Return Value:
return (ULONG) STATUS_REVISION_MISMATCH;
}
status = IoAllocateDriverObjectExtension(DriverObject,
DriverObject,
sizeof(CLASS_DRIVER_EXTENSION),
(PVOID *)&DriverExtension);
if (!NT_SUCCESS(status))
return status;
RtlCopyMemory(&DriverExtension->InitializationData, InitializationData, sizeof(CLASS_INIT_DATA));
DriverExtension->PortNumber = 0;
DriverExtension->RegistryPath.Buffer = ExAllocatePool(PagedPool, RegistryPath->MaximumLength);
if (!DriverExtension->RegistryPath.Buffer)
return STATUS_NO_MEMORY;
DriverExtension->RegistryPath.Length = RegistryPath->Length;
DriverExtension->RegistryPath.MaximumLength = RegistryPath->MaximumLength;
RtlCopyMemory(DriverExtension->RegistryPath.Buffer,
RegistryPath->Buffer,
RegistryPath->Length);
//
// Update driver object with entry points.
//
@ -550,7 +237,6 @@ Return Value:
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiClassDeviceControlDispatch;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = ScsiClassShutdownFlush;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = ScsiClassShutdownFlush;
DriverObject->DriverExtension->AddDevice = ScsiClassAddDevice;
if (InitializationData->ClassStartIo) {
DriverObject->DriverStartIo = InitializationData->ClassStartIo;
@ -562,7 +248,7 @@ Return Value:
do {
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", DriverExtension->PortNumber);
sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber);
DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer));
@ -588,9 +274,9 @@ Return Value:
//
if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData,
portDeviceObject, DriverExtension->PortNumber)) {
portDeviceObject, portNumber)) {
/* deviceFound = TRUE; See note at the end */
deviceFound = TRUE;
}
}
@ -598,12 +284,11 @@ Return Value:
// Check next SCSI adapter.
//
DriverExtension->PortNumber++;
portNumber++;
} while(NT_SUCCESS(status));
/* We don't want to fail init just because we don't have devices right now */
return STATUS_SUCCESS; /*deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;*/
return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;
}