mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
635 lines
19 KiB
C
635 lines
19 KiB
C
/*
|
|
* PROJECT: ReactOS Storage Stack / SCSIPORT storage port library
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
* PURPOSE: Logical Unit (PDO) functions
|
|
* COPYRIGHT: Eric Kohl (eric.kohl@reactos.org)
|
|
* Aleksey Bragin (aleksey@reactos.org)
|
|
* 2020 Victor Perevertkin (victor.perevertkin@reactos.org)
|
|
*/
|
|
|
|
#include "scsiport.h"
|
|
#include "scsitypes.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
PDEVICE_OBJECT
|
|
PdoCreateLunDevice(
|
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
|
PDEVICE_OBJECT LunPDO;
|
|
|
|
ULONG LunExtensionSize = DeviceExtension->LunExtensionSize + sizeof(SCSI_PORT_LUN_EXTENSION);
|
|
|
|
NTSTATUS Status = IoCreateDevice(DeviceExtension->Common.DeviceObject->DriverObject,
|
|
LunExtensionSize,
|
|
NULL,
|
|
FILE_DEVICE_DISK,
|
|
FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
|
|
FALSE,
|
|
&LunPDO);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create a Lun PDO, status: %x\n", Status);
|
|
return NULL;
|
|
}
|
|
|
|
LunExtension = LunPDO->DeviceExtension;
|
|
|
|
/* Zero everything */
|
|
RtlZeroMemory(LunExtension, LunExtensionSize);
|
|
|
|
LunExtension->Common.IsFDO = FALSE;
|
|
LunExtension->Common.DeviceObject = LunPDO;
|
|
LunExtension->Common.LowerDevice = DeviceExtension->Common.DeviceObject;
|
|
|
|
/* Initialize a list of requests */
|
|
InitializeListHead(&LunExtension->SrbInfo.Requests);
|
|
|
|
/* Initialize timeout counter */
|
|
LunExtension->RequestTimeout = -1;
|
|
|
|
/* Set maximum queue size */
|
|
LunExtension->MaxQueueCount = 256;
|
|
|
|
/* Initialize request queue */
|
|
KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
|
|
|
|
LunPDO->Flags |= DO_DIRECT_IO;
|
|
LunPDO->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
return LunPDO;
|
|
}
|
|
|
|
PSCSI_PORT_LUN_EXTENSION
|
|
GetLunByPath(
|
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ UCHAR PathId,
|
|
_In_ UCHAR TargetId,
|
|
_In_ UCHAR Lun)
|
|
{
|
|
if (PathId >= DeviceExtension->NumberOfBuses)
|
|
{
|
|
DPRINT1("Invalid PathId: %u\n", PathId);
|
|
return NULL;
|
|
}
|
|
|
|
PSCSI_BUS_INFO bus = &DeviceExtension->Buses[PathId];
|
|
|
|
for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
|
|
lunEntry != &bus->LunsListHead;
|
|
lunEntry = lunEntry->Flink)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION lunExt =
|
|
CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
|
|
|
|
if (lunExt->PathId == PathId &&
|
|
lunExt->TargetId == TargetId &&
|
|
lunExt->Lun == Lun)
|
|
{
|
|
return lunExt;
|
|
}
|
|
}
|
|
|
|
DPRINT("SCSI LUN (%u, %u, %u) was not found\n", PathId, TargetId, Lun);
|
|
return NULL;
|
|
}
|
|
|
|
PSCSI_REQUEST_BLOCK_INFO
|
|
SpiGetSrbData(
|
|
_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
|
_In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
|
|
_In_ UCHAR QueueTag)
|
|
{
|
|
if (QueueTag == SP_UNTAGGED)
|
|
{
|
|
/* Return the pointer to SrbInfo */
|
|
return &LunExtension->SrbInfo;
|
|
}
|
|
else
|
|
{
|
|
/* Make sure the tag is valid, if it is - return the data */
|
|
if (QueueTag > DeviceExtension->SrbDataCount || QueueTag < 1)
|
|
return NULL;
|
|
else
|
|
return &DeviceExtension->SrbInfo[QueueTag -1];
|
|
}
|
|
}
|
|
|
|
static
|
|
ULONG
|
|
CopyField(
|
|
IN PUCHAR Name,
|
|
IN PCHAR Buffer,
|
|
IN ULONG MaxLength,
|
|
IN CHAR DefaultCharacter,
|
|
IN BOOLEAN Trim)
|
|
{
|
|
ULONG Index;
|
|
|
|
for (Index = 0; Index < MaxLength; Index++)
|
|
{
|
|
if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
|
|
{
|
|
// convert to underscore
|
|
Buffer[Index] = DefaultCharacter;
|
|
}
|
|
else
|
|
{
|
|
// just copy character
|
|
Buffer[Index] = Name[Index];
|
|
}
|
|
}
|
|
|
|
/* Trim trailing default characters */
|
|
if (Trim)
|
|
{
|
|
Index = MaxLength - 1;
|
|
for (;;)
|
|
{
|
|
if (Buffer[Index] != DefaultCharacter)
|
|
{
|
|
Index++;
|
|
break;
|
|
}
|
|
|
|
Index--;
|
|
}
|
|
}
|
|
|
|
return Index;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleQueryDeviceText(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
PIO_STACK_LOCATION IoStack;
|
|
UINT32 Offset = 0;
|
|
PINQUIRYDATA InquiryData;
|
|
CHAR LocalBuffer[64];
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING DeviceDescription;
|
|
|
|
DPRINT("PdoHandleQueryDeviceText\n");
|
|
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
InquiryData = &DeviceExtension->InquiryData;
|
|
|
|
switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
|
|
{
|
|
case DeviceTextDescription:
|
|
{
|
|
DPRINT("DeviceTextDescription\n");
|
|
|
|
Offset += CopyField(InquiryData->VendorId,
|
|
&LocalBuffer[Offset],
|
|
sizeof(InquiryData->VendorId),
|
|
' ',
|
|
TRUE);
|
|
LocalBuffer[Offset++] = ' ';
|
|
Offset += CopyField(InquiryData->ProductId,
|
|
&LocalBuffer[Offset],
|
|
sizeof(InquiryData->ProductId),
|
|
' ',
|
|
TRUE);
|
|
Offset += sprintf(&LocalBuffer[Offset],
|
|
" SCSI %s Device",
|
|
GetDeviceType(InquiryData));
|
|
LocalBuffer[Offset++] = '\0';
|
|
|
|
RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
|
|
|
|
DeviceDescription.Length = 0;
|
|
DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR));
|
|
DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
DeviceDescription.MaximumLength,
|
|
TAG_SCSIPORT);
|
|
if (!DeviceDescription.Buffer)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
case DeviceTextLocationInformation:
|
|
{
|
|
DPRINT("DeviceTextLocationInformation\n");
|
|
|
|
sprintf(LocalBuffer, "Bus Number %d, Target ID %d, LUN %d",
|
|
DeviceExtension->PathId, DeviceExtension->TargetId, DeviceExtension->Lun);
|
|
|
|
RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
|
|
|
|
DeviceDescription.Length = 0;
|
|
DeviceDescription.MaximumLength = (USHORT)((strlen(LocalBuffer) + 1) * sizeof(WCHAR));
|
|
DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
DeviceDescription.MaximumLength,
|
|
TAG_SCSIPORT);
|
|
if (!DeviceDescription.Buffer)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
default:
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
}
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleQueryDeviceId(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION DeviceExtension;
|
|
NTSTATUS Status;
|
|
CHAR Buffer[100] = {0};
|
|
LPCSTR DeviceType;
|
|
ULONG Offset = 0;
|
|
PINQUIRYDATA InquiryData;
|
|
ANSI_STRING AnsiString;
|
|
UNICODE_STRING DeviceId;
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
InquiryData = &DeviceExtension->InquiryData;
|
|
|
|
DeviceType = GetDeviceType(InquiryData);
|
|
|
|
// lets create device string
|
|
Offset = sprintf(&Buffer[Offset], "SCSI\\");
|
|
Offset += sprintf(&Buffer[Offset], DeviceType);
|
|
Offset += sprintf(&Buffer[Offset], "&Ven_");
|
|
Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8, '_', TRUE);
|
|
Offset += sprintf(&Buffer[Offset], "&Prod_");
|
|
Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16, '_', TRUE);
|
|
Offset += sprintf(&Buffer[Offset], "&Rev_");
|
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4, '_', TRUE);
|
|
Buffer[Offset] = '\0';
|
|
|
|
RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
|
|
|
|
// allocate DeviceId string
|
|
Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, TRUE);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
|
|
}
|
|
|
|
DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
ConvertToUnicodeString(
|
|
IN CHAR * Buffer,
|
|
IN ULONG ResultBufferLength,
|
|
IN ULONG ResultBufferOffset,
|
|
OUT LPWSTR ResultBuffer,
|
|
OUT PULONG NewResultBufferOffset)
|
|
{
|
|
UNICODE_STRING DeviceString;
|
|
ANSI_STRING AnsiString;
|
|
NTSTATUS Status;
|
|
|
|
ASSERT(ResultBufferLength);
|
|
ASSERT(ResultBufferLength > ResultBufferOffset);
|
|
|
|
DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n",
|
|
ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
|
|
|
|
// construct destination string
|
|
DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
|
|
DeviceString.Length = 0;
|
|
DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
|
|
|
|
// initialize source string
|
|
RtlInitAnsiString(&AnsiString, Buffer);
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
|
|
ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
// subtract consumed bytes
|
|
ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
|
|
ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
|
|
|
|
*NewResultBufferOffset = ResultBufferOffset;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleQueryHardwareId(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
|
|
LPCSTR GenericType, DeviceType;
|
|
LPWSTR Buffer;
|
|
CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
|
|
ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length, Id6Length;
|
|
ULONG Offset, TotalLength, Length;
|
|
PINQUIRYDATA InquiryData;
|
|
|
|
InquiryData = &PDODeviceExtension->InquiryData;
|
|
|
|
DeviceType = GetDeviceType(InquiryData);
|
|
GenericType = GetGenericType(InquiryData);
|
|
|
|
ASSERT(GenericType);
|
|
|
|
// generate id 1
|
|
// SCSI\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
|
|
RtlZeroMemory(Id1, sizeof(Id1));
|
|
Offset = 0;
|
|
Offset = sprintf(&Id1[Offset], "SCSI\\");
|
|
Offset += sprintf(&Id1[Offset], DeviceType);
|
|
Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4, '_', FALSE);
|
|
Id1Length = strlen(Id1) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
|
|
|
|
// generate id 2
|
|
// SCSI\SCSIType_VendorId(8)_ProductId(16)
|
|
RtlZeroMemory(Id2, sizeof(Id2));
|
|
Offset = 0;
|
|
Offset = sprintf(&Id2[Offset], "SCSI\\");
|
|
Offset += sprintf(&Id2[Offset], DeviceType);
|
|
Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16, '_', FALSE);
|
|
Id2Length = strlen(Id2) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
|
|
|
|
// generate id 3
|
|
// SCSI\SCSIType_VendorId(8)
|
|
RtlZeroMemory(Id3, sizeof(Id3));
|
|
Offset = 0;
|
|
Offset = sprintf(&Id3[Offset], "SCSI\\");
|
|
Offset += sprintf(&Id3[Offset], DeviceType);
|
|
Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8, '_', FALSE);
|
|
Id3Length = strlen(Id3) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
|
|
|
|
// generate id 4
|
|
// SCSI\VendorId(8)_ProductId(16)_Revision(1)
|
|
RtlZeroMemory(Id4, sizeof(Id4));
|
|
Offset = 0;
|
|
Offset = sprintf(&Id4[Offset], "SCSI\\");
|
|
Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1, '_', FALSE);
|
|
Id4Length = strlen(Id4) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
|
|
|
|
// generate id 5
|
|
// VendorId(8)_ProductId(16)_Revision(1)
|
|
RtlZeroMemory(Id5, sizeof(Id5));
|
|
Offset = 0;
|
|
Offset = CopyField(InquiryData->VendorId, &Id5[Offset], 8, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductId, &Id5[Offset], 16, '_', FALSE);
|
|
Offset += CopyField(InquiryData->ProductRevisionLevel, &Id5[Offset], 1, '_', FALSE);
|
|
Id5Length = strlen(Id5) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
|
|
|
|
// generate id 6
|
|
// SCSIType
|
|
RtlZeroMemory(Id6, sizeof(Id6));
|
|
Offset = 0;
|
|
Offset = sprintf(&Id6[Offset], GenericType);
|
|
Id6Length = strlen(Id6) + 1;
|
|
DPRINT("PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
|
|
|
|
TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1;
|
|
|
|
Buffer = ExAllocatePoolWithTag(PagedPool, TotalLength * sizeof(WCHAR), TAG_SCSIPORT);
|
|
if (!Buffer)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// reset offset
|
|
Offset = 0;
|
|
Length = TotalLength;
|
|
|
|
ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
|
|
ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
|
|
ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
|
|
ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
|
|
ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
|
|
ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
|
|
|
|
Buffer[Offset] = UNICODE_NULL;
|
|
|
|
ASSERT(Offset + 1 == Length);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)Buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleQueryCompatibleId(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
|
|
CHAR Buffer[100] = {0};
|
|
ULONG Length, Offset;
|
|
LPWSTR InstanceId;
|
|
LPCSTR DeviceType;
|
|
|
|
DeviceType = GetDeviceType(&PDODeviceExtension->InquiryData);
|
|
|
|
// format instance id
|
|
Length = sprintf(Buffer, "SCSI\\%s", DeviceType) + 1;
|
|
Length += sprintf(&Buffer[Length], "SCSI\\%s", "RAW") + 2;
|
|
|
|
InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
|
|
if (!InstanceId)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
|
|
ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
|
|
|
|
InstanceId[Offset] = UNICODE_NULL;
|
|
|
|
DPRINT("PdoHandleQueryCompatibleId %S\n", InstanceId);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleQueryInstanceId(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
|
WCHAR Buffer[26];
|
|
ULONG Length;
|
|
LPWSTR InstanceId;
|
|
|
|
// use instance count and LUN
|
|
swprintf(Buffer, L"%x%x%x", lunExt->PathId, lunExt->TargetId, lunExt->Lun);
|
|
|
|
Length = wcslen(Buffer) + 1;
|
|
|
|
InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
|
|
if (!InstanceId)
|
|
{
|
|
Irp->IoStatus.Information = 0;
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
wcscpy(InstanceId, Buffer);
|
|
|
|
DPRINT("PdoHandleQueryInstanceId %S\n", InstanceId);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
PdoHandleDeviceRelations(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PDEVICE_RELATIONS deviceRelations;
|
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
// check if relation type is BusRelations
|
|
if (ioStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
|
|
{
|
|
// PDO handles only target device relation
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
deviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_SCSIPORT);
|
|
if (!deviceRelations)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// initialize device relations
|
|
deviceRelations->Count = 1;
|
|
deviceRelations->Objects[0] = DeviceObject;
|
|
ObReferenceObject(DeviceObject);
|
|
|
|
Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PdoDispatchPnp(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_Inout_ PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
|
|
PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
|
|
DPRINT("PDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction));
|
|
|
|
ASSERT(!lunExt->Common.IsFDO);
|
|
|
|
switch (ioStack->MinorFunction)
|
|
{
|
|
case IRP_MN_START_DEVICE:
|
|
{
|
|
RegistryInitLunKey(lunExt);
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
{
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
{
|
|
status = PdoHandleDeviceRelations(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
|
{
|
|
status = PdoHandleQueryDeviceText(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
case IRP_MN_QUERY_ID:
|
|
{
|
|
DPRINT("IRP_MN_QUERY_ID IdType %s\n",
|
|
DbgGetDeviceIDString(ioStack->Parameters.QueryId.IdType));
|
|
|
|
if (ioStack->Parameters.QueryId.IdType == BusQueryDeviceID)
|
|
{
|
|
status = PdoHandleQueryDeviceId(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
|
|
{
|
|
status = PdoHandleQueryHardwareId(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryInstanceID)
|
|
{
|
|
status = PdoHandleQueryInstanceId(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
else if (ioStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
|
|
{
|
|
status = PdoHandleQueryCompatibleId(DeviceObject, Irp);
|
|
break;
|
|
}
|
|
|
|
// fallthrough
|
|
}
|
|
default:
|
|
{
|
|
// do nothing
|
|
status = Irp->IoStatus.Status;
|
|
}
|
|
}
|
|
|
|
if (status != STATUS_PENDING)
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return status;
|
|
}
|