[ISAPNP] Create PDO identifiers ahead of IRP_MN_QUERY_ID
authorHervé Poussineau <hpoussin@reactos.org>
Mon, 16 Mar 2020 18:00:00 +0000 (19:00 +0100)
committerHervé Poussineau <hpoussin@reactos.org>
Fri, 20 Mar 2020 21:40:11 +0000 (22:40 +0100)
drivers/bus/isapnp/isapnp.c
drivers/bus/isapnp/isapnp.h
drivers/bus/isapnp/pdo.c

index 6fc29e9..0382f8c 100644 (file)
 #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;
 
index e247643..3321ff8 100644 (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(
index 4a674a0..78026a3 100644 (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;
 }