From e0607fcebf0f93ed2b5be062771ca2300cc73196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Mon, 16 Mar 2020 19:00:00 +0100 Subject: [PATCH] [ISAPNP] Create PDO identifiers ahead of IRP_MN_QUERY_ID --- drivers/bus/isapnp/isapnp.c | 134 ++++++++++++++++++++++++++++++++++++ drivers/bus/isapnp/isapnp.h | 13 ++++ drivers/bus/isapnp/pdo.c | 68 +++++------------- 3 files changed, 163 insertions(+), 52 deletions(-) diff --git a/drivers/bus/isapnp/isapnp.c b/drivers/bus/isapnp/isapnp.c index 6fc29e9e70c..0382f8c843d 100644 --- a/drivers/bus/isapnp/isapnp.c +++ b/drivers/bus/isapnp/isapnp.c @@ -10,6 +10,132 @@ #define NDEBUG #include +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; diff --git a/drivers/bus/isapnp/isapnp.h b/drivers/bus/isapnp/isapnp.h index e247643112c..3321ff8b9ec 100644 --- a/drivers/bus/isapnp/isapnp.h +++ b/drivers/bus/isapnp/isapnp.h @@ -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( diff --git a/drivers/bus/isapnp/pdo.c b/drivers/bus/isapnp/pdo.c index 4a674a05e0f..78026a3b40a 100644 --- a/drivers/bus/isapnp/pdo.c +++ b/drivers/bus/isapnp/pdo.c @@ -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; }