https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e0607fcebf0f93ed2b5be062771ca2300cc73196

commit e0607fcebf0f93ed2b5be062771ca2300cc73196
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Mon Mar 16 19:00:00 2020 +0100
Commit:     Hervé Poussineau <[email protected]>
CommitDate: Fri Mar 20 22:40:11 2020 +0100

    [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 <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;
 
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;
 }

Reply via email to