[ISAPNP] Create PDO identifiers ahead of IRP_MN_QUERY_ID

This commit is contained in:
Hervé Poussineau 2020-03-16 19:00:00 +01:00
parent 89aff07a67
commit e0607fcebf
3 changed files with 163 additions and 52 deletions

View file

@ -10,6 +10,132 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
NTSTATUS
NTAPI
IsaPnpDuplicateUnicodeString(
IN ULONG Flags,
IN PCUNICODE_STRING SourceString,
OUT PUNICODE_STRING DestinationString)
{
if (SourceString == NULL ||
DestinationString == NULL ||
SourceString->Length > SourceString->MaximumLength ||
(SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) ||
Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING ||
Flags >= 4)
{
return STATUS_INVALID_PARAMETER;
}
if ((SourceString->Length == 0) &&
(Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
DestinationString->Buffer = NULL;
}
else
{
USHORT DestMaxLength = SourceString->Length;
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
DestMaxLength += sizeof(UNICODE_NULL);
DestinationString->Buffer = ExAllocatePool(PagedPool, DestMaxLength);
if (DestinationString->Buffer == NULL)
return STATUS_NO_MEMORY;
RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
DestinationString->Length = SourceString->Length;
DestinationString->MaximumLength = DestMaxLength;
if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
}
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
IsaFdoCreateDeviceIDs(
IN PISAPNP_PDO_EXTENSION PdoExt)
{
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
UNICODE_STRING TempString;
WCHAR TempBuffer[256];
PWCHAR End;
NTSTATUS Status;
USHORT i;
TempString.Buffer = TempBuffer;
TempString.MaximumLength = sizeof(TempBuffer);
TempString.Length = 0;
/* Device ID */
Status = RtlStringCbPrintfExW(TempString.Buffer,
TempString.MaximumLength / sizeof(WCHAR),
&End,
NULL, 0,
L"ISAPNP\\%3S%04X",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_SUCCESS(Status))
return Status;
TempString.Length = (End - TempString.Buffer) * sizeof(WCHAR);
Status = IsaPnpDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&TempString,
&PdoExt->DeviceID);
if (!NT_SUCCESS(Status))
return Status;
/* HardwareIDs */
Status = RtlStringCbPrintfExW(TempString.Buffer,
TempString.MaximumLength / sizeof(WCHAR),
&End,
NULL, 0,
L"ISAPNP\\%3S%04X@"
L"*%3S%04X@",
LogDev->VendorId,
LogDev->ProdId,
LogDev->VendorId,
LogDev->ProdId);
if (!NT_SUCCESS(Status))
return Status;
TempString.Length = (End - TempString.Buffer) * sizeof(WCHAR);
Status = IsaPnpDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&TempString,
&PdoExt->HardwareIDs);
if (!NT_SUCCESS(Status))
return Status;
for (i = 0; i < PdoExt->HardwareIDs.Length / sizeof(WCHAR); i++)
if (PdoExt->HardwareIDs.Buffer[i] == '@')
PdoExt->HardwareIDs.Buffer[i] = UNICODE_NULL;
/* InstanceID */
Status = RtlStringCbPrintfExW(TempString.Buffer,
TempString.MaximumLength / sizeof(WCHAR),
&End,
NULL, 0,
L"%X",
LogDev->SerialNumber);
if (!NT_SUCCESS(Status))
return Status;
TempString.Length = (End - TempString.Buffer) * sizeof(WCHAR);
Status = IsaPnpDuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&TempString,
&PdoExt->InstanceID);
if (!NT_SUCCESS(Status))
return Status;
return STATUS_SUCCESS;
}
NTSTATUS NTSTATUS
NTAPI NTAPI
IsaPnpFillDeviceRelations( IsaPnpFillDeviceRelations(
@ -61,6 +187,14 @@ IsaPnpFillDeviceRelations(
PdoExt->Common.Self = IsaDevice->Pdo; PdoExt->Common.Self = IsaDevice->Pdo;
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
PdoExt->IsaPnpDevice = IsaDevice; PdoExt->IsaPnpDevice = IsaDevice;
Status = IsaFdoCreateDeviceIDs(PdoExt);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(IsaDevice->Pdo);
IsaDevice->Pdo = NULL;
break;
}
} }
DeviceRelations->Objects[i++] = IsaDevice->Pdo; DeviceRelations->Objects[i++] = IsaDevice->Pdo;

View file

@ -47,10 +47,23 @@ typedef struct _ISAPNP_FDO_EXTENSION {
typedef struct _ISAPNP_PDO_EXTENSION { typedef struct _ISAPNP_PDO_EXTENSION {
ISAPNP_COMMON_EXTENSION Common; ISAPNP_COMMON_EXTENSION Common;
PISAPNP_LOGICAL_DEVICE IsaPnpDevice; PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
UNICODE_STRING DeviceID;
UNICODE_STRING HardwareIDs;
UNICODE_STRING InstanceID;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION; } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
/* isapnp.c */ /* isapnp.c */
#define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE 1
#define RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING 2
NTSTATUS
NTAPI
IsaPnpDuplicateUnicodeString(
IN ULONG Flags,
IN PCUNICODE_STRING SourceString,
OUT PUNICODE_STRING DestinationString);
NTSTATUS NTSTATUS
NTAPI NTAPI
IsaPnpFillDeviceRelations( IsaPnpFillDeviceRelations(

View file

@ -62,79 +62,43 @@ IsaPdoQueryId(
IN PIRP Irp, IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp) IN PIO_STACK_LOCATION IrpSp)
{ {
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice; UNICODE_STRING EmptyString = RTL_CONSTANT_STRING(L"");
WCHAR Temp[256]; PUNICODE_STRING Source;
PWCHAR Buffer, End; PWCHAR Buffer;
ULONG Length;
NTSTATUS Status;
switch (IrpSp->Parameters.QueryId.IdType) switch (IrpSp->Parameters.QueryId.IdType)
{ {
case BusQueryDeviceID: case BusQueryDeviceID:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
Status = RtlStringCbPrintfExW(Temp, sizeof(Temp), Source = &PdoExt->DeviceID;
&End,
NULL, 0,
L"ISAPNP\\%3S%04X",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_SUCCESS(Status))
return Status;
Length = End - Temp;
Temp[Length++] = UNICODE_NULL;
break; break;
}
case BusQueryHardwareIDs: case BusQueryHardwareIDs:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n"); DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
Status = RtlStringCbPrintfExW(Temp, sizeof(Temp), Source = &PdoExt->HardwareIDs;
&End, break;
NULL, 0,
L"ISAPNP\\%3S%04X", case BusQueryCompatibleIDs:
LogDev->VendorId, DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
LogDev->ProdId); Source = &EmptyString;
if (!NT_SUCCESS(Status))
return Status;
Length = End - Temp;
Temp[Length++] = UNICODE_NULL;
Status = RtlStringCbPrintfExW(Temp + Length, sizeof(Temp) - Length,
&End,
NULL, 0,
L"*%3S%04X",
LogDev->VendorId,
LogDev->ProdId);
if (!NT_SUCCESS(Status))
return Status;
Length = End - Temp;
Temp[Length++] = UNICODE_NULL;
Temp[Length++] = UNICODE_NULL;
break; break;
case BusQueryInstanceID: case BusQueryInstanceID:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
Status = RtlStringCbPrintfExW(Temp, sizeof(Temp), Source = &PdoExt->InstanceID;
&End,
NULL, 0,
L"%X",
LogDev->SerialNumber);
if (!NT_SUCCESS(Status))
return Status;
Length = End - Temp;
Temp[Length++] = UNICODE_NULL;
break; break;
default: default:
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n",
IrpSp->Parameters.QueryId.IdType); IrpSp->Parameters.QueryId.IdType);
return Irp->IoStatus.Status; return Irp->IoStatus.Status;
} }
Buffer = ExAllocatePool(PagedPool, Length * sizeof(WCHAR)); Buffer = ExAllocatePool(PagedPool, Source->MaximumLength);
if (!Buffer) if (!Buffer)
return STATUS_NO_MEMORY; return STATUS_NO_MEMORY;
RtlCopyMemory(Buffer, Temp, Length * sizeof(WCHAR)); RtlCopyMemory(Buffer, Source->Buffer, Source->MaximumLength);
Irp->IoStatus.Information = (ULONG_PTR)Buffer; Irp->IoStatus.Information = (ULONG_PTR)Buffer;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }