#include <include/class2.h>
#include <stdio.h>
+/* Part of the drive letter hack */
+#include <ntifs.h>
+#include <ketypes.h>
+
//#define NDEBUG
#include <debug.h>
#define START_UNIT_TIMEOUT 30
/* Disk layout used by Windows NT4 and earlier versions. */
-#define DEFAULT_SECTORS_PER_TRACK 32
-#define DEFAULT_TRACKS_PER_CYLINDER 64
+//#define DEFAULT_SECTORS_PER_TRACK 32
+//#define DEFAULT_TRACKS_PER_CYLINDER 64
/* Disk layout used by Windows 2000 and later versions. */
-//#define DEFAULT_SECTORS_PER_TRACK 63
-//#define DEFAULT_TRACKS_PER_CYLINDER 255
+#define DEFAULT_SECTORS_PER_TRACK 63
+#define DEFAULT_TRACKS_PER_CYLINDER 255
NTSTATUS
NTAPI
return STATUS_SUCCESS;
}
+/* The following hack to assign drive letters with a non-PnP storage stack */
+
+typedef struct _CLASS_DEVICE_INFO {
+ ULONG Partitions;
+ ULONG DeviceNumber;
+ ULONG DriveNumber;
+ PDEVICE_OBJECT LowerDevice;
+} CLASS_DEVICE_INFO, *PCLASS_DEVICE_INFO;
+
+typedef struct _CLASS_DRIVER_EXTENSION {
+ ULONG PortNumber;
+ 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 */
+ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\HardDisk%d\\Partition0", 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 */
+ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\??\\PhysicalDrive%d", 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);
+
+ /* Create the symbolic link to PhysicalDriveX */
+ PartitionU.Length = swprintf(PartitionU.Buffer, L"\\Device\\Harddisk%d\\Partition0", DeviceNumber) * sizeof(WCHAR);
+ DriveLetterU.Length = swprintf(DriveLetterU.Buffer, L"\\??\\PhysicalDrive%d", DriveNumber) * sizeof(WCHAR);
+
+ Status = IoCreateSymbolicLink(&DriveLetterU, &PartitionU);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to create symbolic link */
+ return Status;
+ }
+
+ DbgPrint("HACK: Created symbolic link %wZ -> %wZ\n", &PartitionU, &DriveLetterU);
+
+ 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++;
+ }
+ }
+
+ DeviceInfo->DeviceNumber = DeviceNumber;
+ DeviceInfo->DriveNumber = DriveNumber;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+ScsiClassPlugPlay(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ if (IrpSp->MinorFunction == IRP_MN_START_DEVICE)
+ {
+ IoSkipCurrentIrpStackLocation(Irp);
+ return STATUS_SUCCESS;
+ }
+ else if (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)
+ {
+ PCLASS_DEVICE_INFO DeviceInfo = DeviceObject->DeviceExtension;
+
+ ScsiClassRemoveDriveLetter(DeviceInfo);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ IoDetachDevice(DeviceInfo->LowerDevice);
+ IoDeleteDevice(DeviceObject);
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ 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, NULL, &DriverExtension->InitializationData,
+ PhysicalDeviceObject, DriverExtension->PortNumber))
+ {
+ /* Create a device object */
+ Status = IoCreateDevice(DriverObject,
+ sizeof(CLASS_DEVICE_INFO),
+ NULL,
+ FILE_DEVICE_DISK,
+ 0,
+ FALSE,
+ &DeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ DeviceInfo = DeviceObject->DeviceExtension;
+ RtlZeroMemory(DeviceInfo, sizeof(CLASS_DEVICE_INFO));
+
+ /* Attach it to the PDO */
+ DeviceInfo->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
+
+ /* 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 ---- */
+
+
\f
ULONG
NTAPI
PDRIVER_OBJECT DriverObject = Argument1;
- ULONG portNumber = 0;
PDEVICE_OBJECT portDeviceObject;
NTSTATUS status;
STRING deviceNameString;
PFILE_OBJECT fileObject;
CCHAR deviceNameBuffer[256];
BOOLEAN deviceFound = FALSE;
+ PCLASS_DRIVER_EXTENSION DriverExtension;
DebugPrint((3,"\n\nSCSI Class Driver\n"));
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;
+
//
// Update driver object with entry points.
//
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiClassReadWrite;
+ DriverObject->MajorFunction[IRP_MJ_PNP] = ScsiClassPlugPlay;
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiClassInternalIoControl;
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;
do {
- sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", portNumber);
+ sprintf(deviceNameBuffer, "\\Device\\ScsiPort%lu", DriverExtension->PortNumber);
DebugPrint((2, "ScsiClassInitialize: Open Port %s\n", deviceNameBuffer));
//
if (InitializationData->ClassFindDevices(DriverObject, Argument2, InitializationData,
- portDeviceObject, portNumber)) {
+ portDeviceObject, DriverExtension->PortNumber)) {
deviceFound = TRUE;
}
// Check next SCSI adapter.
//
- portNumber++;
+ DriverExtension->PortNumber++;
} while(NT_SUCCESS(status));
- return deviceFound ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;
+ /* 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;*/
}
\f
srb,
irpStack->MajorFunction,
irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
- MAXIMUM_RETRIES - ((ULONG_PTR)irpStack->Parameters.Others.Argument4),
+ MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
&status);
//
srb,
irpStack->MajorFunction,
irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
- MAXIMUM_RETRIES - ((ULONG_PTR)irpStack->Parameters.Others.Argument4),
+ MAXIMUM_RETRIES - PtrToUlong(irpStack->Parameters.Others.Argument4),
&status);
//