[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
#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
NTAPI
IsaPnpFillDeviceRelations(
@ -61,6 +187,14 @@ IsaPnpFillDeviceRelations(
PdoExt->Common.Self = IsaDevice->Pdo;
PdoExt->Common.State = dsStopped;
PdoExt->IsaPnpDevice = IsaDevice;
Status = IsaFdoCreateDeviceIDs(PdoExt);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(IsaDevice->Pdo);
IsaDevice->Pdo = NULL;
break;
}
}
DeviceRelations->Objects[i++] = IsaDevice->Pdo;

View file

@ -47,10 +47,23 @@ typedef struct _ISAPNP_FDO_EXTENSION {
typedef struct _ISAPNP_PDO_EXTENSION {
ISAPNP_COMMON_EXTENSION Common;
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
UNICODE_STRING DeviceID;
UNICODE_STRING HardwareIDs;
UNICODE_STRING InstanceID;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
/* 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
NTAPI
IsaPnpFillDeviceRelations(

View file

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