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

commit 9bcd83507467c4c56195e5a342e0d60ff07a2068
Author:     Thomas Faber <[email protected]>
AuthorDate: Tue Aug 6 19:54:40 2019 +0200
Commit:     Thomas Faber <[email protected]>
CommitDate: Sat Apr 11 23:42:59 2020 +0200

    [ACPI_APITEST] Add a unit test for Bus_PDO_QueryResourceRequirements. 
CORE-12892
    
    This will allow us to verify fixes made to function, which is quite broken.
---
 drivers/bus/acpi/acpica/include/acpi.h             |   2 +-
 drivers/bus/acpi/buspdo.c                          |   6 +-
 modules/rostests/apitests/CMakeLists.txt           |   1 +
 .../acpi/Bus_PDO_QueryResourceRequirements.c       | 530 +++++++++++++++++++++
 modules/rostests/apitests/acpi/CMakeLists.txt      |  12 +
 modules/rostests/apitests/acpi/testlist.c          |  10 +
 6 files changed, 558 insertions(+), 3 deletions(-)

diff --git a/drivers/bus/acpi/acpica/include/acpi.h 
b/drivers/bus/acpi/acpica/include/acpi.h
index 6519a5139a6..afc92503d63 100644
--- a/drivers/bus/acpi/acpica/include/acpi.h
+++ b/drivers/bus/acpi/acpica/include/acpi.h
@@ -44,7 +44,7 @@
 #ifndef __ACPI_H__
 #define __ACPI_H__
 
-#ifdef __REACTOS__
+#if defined(__REACTOS__) && !defined(UNIT_TEST)
 /*
  * Header inclusion HACK.
  */
diff --git a/drivers/bus/acpi/buspdo.c b/drivers/bus/acpi/buspdo.c
index ac43a847dd5..61607abb44f 100644
--- a/drivers/bus/acpi/buspdo.c
+++ b/drivers/bus/acpi/buspdo.c
@@ -1,3 +1,4 @@
+#ifndef UNIT_TEST
 #include "precomp.h"
 
 #include <initguid.h>
@@ -1294,6 +1295,7 @@ Bus_PDO_QueryResources(
     Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
     return STATUS_SUCCESS;
 }
+#endif /* UNIT_TEST */
 
 NTSTATUS
 Bus_PDO_QueryResourceRequirements(
@@ -1796,6 +1798,7 @@ Bus_PDO_QueryResourceRequirements(
     return STATUS_SUCCESS;
 }
 
+#ifndef UNIT_TEST
 NTSTATUS
 Bus_PDO_QueryDeviceRelations(
      PPDO_DEVICE_DATA     DeviceData,
@@ -2040,5 +2043,4 @@ GetDeviceCapabilitiesExit:
     return status;
 
 }
-
-
+#endif /* UNIT_TEST */
diff --git a/modules/rostests/apitests/CMakeLists.txt 
b/modules/rostests/apitests/CMakeLists.txt
index 9f1d6ce225b..752755a453f 100644
--- a/modules/rostests/apitests/CMakeLists.txt
+++ b/modules/rostests/apitests/CMakeLists.txt
@@ -3,6 +3,7 @@ PROJECT(ApiTests)
 
 include_directories(include)
 
+add_subdirectory(acpi)
 add_subdirectory(advapi32)
 add_subdirectory(afd)
 add_subdirectory(apphelp)
diff --git a/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c 
b/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c
new file mode 100644
index 00000000000..08a7a13dd4c
--- /dev/null
+++ b/modules/rostests/apitests/acpi/Bus_PDO_QueryResourceRequirements.c
@@ -0,0 +1,530 @@
+/*
+ * PROJECT:     ReactOS API Tests
+ * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Unit Tests for acpi!Bus_PDO_QueryResourceRequirements
+ * COPYRIGHT:   Copyright 2017-2020 Thomas Faber ([email protected])
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <ndk/rtlfuncs.h>
+#define UNIT_TEST
+#include <acpi.h>
+
+/* Kernel definitions (copied) */
+#define IO_RESOURCE_PREFERRED             0x01
+#define IO_RESOURCE_DEFAULT               0x02
+#define IO_RESOURCE_ALTERNATIVE           0x08
+
+typedef struct _IO_RESOURCE_DESCRIPTOR {
+  UCHAR Option;
+  UCHAR Type;
+  UCHAR ShareDisposition;
+  UCHAR Spare1;
+  USHORT Flags;
+  USHORT Spare2;
+  union {
+    struct {
+      ULONG Length;
+      ULONG Alignment;
+      PHYSICAL_ADDRESS MinimumAddress;
+      PHYSICAL_ADDRESS MaximumAddress;
+    } Port;
+    struct {
+      ULONG Length;
+      ULONG Alignment;
+      PHYSICAL_ADDRESS MinimumAddress;
+      PHYSICAL_ADDRESS MaximumAddress;
+    } Memory;
+    struct {
+      ULONG MinimumVector;
+      ULONG MaximumVector;
+    } Interrupt;
+    struct {
+      ULONG MinimumChannel;
+      ULONG MaximumChannel;
+    } Dma;
+    struct {
+      ULONG Length;
+      ULONG Alignment;
+      PHYSICAL_ADDRESS MinimumAddress;
+      PHYSICAL_ADDRESS MaximumAddress;
+    } Generic;
+    struct {
+      ULONG Data[3];
+    } DevicePrivate;
+    struct {
+      ULONG Length;
+      ULONG MinBusNumber;
+      ULONG MaxBusNumber;
+      ULONG Reserved;
+    } BusNumber;
+    struct {
+      ULONG Priority;
+      ULONG Reserved1;
+      ULONG Reserved2;
+    } ConfigData;
+  } u;
+} IO_RESOURCE_DESCRIPTOR, *PIO_RESOURCE_DESCRIPTOR;
+
+typedef struct _IO_RESOURCE_LIST {
+  USHORT Version;
+  USHORT Revision;
+  ULONG Count;
+  IO_RESOURCE_DESCRIPTOR Descriptors[1];
+} IO_RESOURCE_LIST, *PIO_RESOURCE_LIST;
+
+typedef struct _IO_RESOURCE_REQUIREMENTS_LIST {
+  ULONG ListSize;
+  INTERFACE_TYPE InterfaceType;
+  ULONG BusNumber;
+  ULONG SlotNumber;
+  ULONG Reserved[3];
+  ULONG AlternativeLists;
+  IO_RESOURCE_LIST List[1];
+} IO_RESOURCE_REQUIREMENTS_LIST, *PIO_RESOURCE_REQUIREMENTS_LIST;
+
+/* Kernel definitions (mock) */
+#define PAGED_CODE()
+#define DPRINT1(...) do { if (0) DbgPrint(__VA_ARGS__); } while (0)
+
+typedef struct _IRP
+{
+    IO_STATUS_BLOCK IoStatus;
+} IRP, *PIRP;
+
+#define PagedPool 1
+static
+PVOID
+ExAllocatePoolWithTag(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
+{
+    PVOID *Mem;
+
+    Mem = HeapAlloc(GetProcessHeap(), 0, NumberOfBytes + 2 * sizeof(PVOID));
+    Mem[0] = (PVOID)NumberOfBytes;
+    Mem[1] = (PVOID)(ULONG_PTR)Tag;
+    return Mem + 2;
+}
+
+static
+VOID
+ExFreePoolWithTag(PVOID MemPtr, ULONG Tag)
+{
+    PVOID *Mem = MemPtr;
+
+    Mem -= 2;
+    ok(Mem[1] == (PVOID)(ULONG_PTR)Tag, "Tag is %lx, expected %p\n", Tag, 
Mem[1]);
+    HeapFree(GetProcessHeap(), 0, Mem);
+}
+
+static
+SIZE_T
+GetPoolAllocSize(PVOID MemPtr)
+{
+    PVOID *Mem = MemPtr;
+
+    Mem -= 2;
+    return (SIZE_T)Mem[0];
+}
+
+/* ACPI driver definitions */
+typedef struct _PDO_DEVICE_DATA
+{
+    HANDLE AcpiHandle;
+    PWCHAR HardwareIDs;
+} PDO_DEVICE_DATA, *PPDO_DEVICE_DATA;
+
+/* ACPICA functions (mock) */
+static BOOLEAN AcpiCallExpected;
+static ACPI_HANDLE CorrectHandle = &CorrectHandle;
+static ACPI_BUFFER CurrentBuffer;
+static ACPI_BUFFER PossibleBuffer;
+
+ACPI_STATUS
+AcpiGetCurrentResources (
+    ACPI_HANDLE             Device,
+    ACPI_BUFFER             *RetBuffer)
+{
+    ok(AcpiCallExpected, "Unexpected call to AcpiGetCurrentResources\n");
+    ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, 
CorrectHandle);
+    if (RetBuffer->Length < CurrentBuffer.Length)
+    {
+        RetBuffer->Length = CurrentBuffer.Length;
+        return AE_BUFFER_OVERFLOW;
+    }
+    RetBuffer->Length = CurrentBuffer.Length;
+    CopyMemory(RetBuffer->Pointer, CurrentBuffer.Pointer, 
CurrentBuffer.Length);
+    return AE_OK;
+}
+
+ACPI_STATUS
+AcpiGetPossibleResources (
+    ACPI_HANDLE             Device,
+    ACPI_BUFFER             *RetBuffer)
+{
+    ok(AcpiCallExpected, "Unexpected call to AcpiGetPossibleResources\n");
+    ok(Device == CorrectHandle, "Device = %p, expected %p\n", Device, 
CorrectHandle);
+    if (RetBuffer->Length < PossibleBuffer.Length)
+    {
+        RetBuffer->Length = PossibleBuffer.Length;
+        return AE_BUFFER_OVERFLOW;
+    }
+    RetBuffer->Length = PossibleBuffer.Length;
+    CopyMemory(RetBuffer->Pointer, PossibleBuffer.Pointer, 
PossibleBuffer.Length);
+    return AE_OK;
+}
+
+#include "../../../../drivers/bus/acpi/buspdo.c"
+
+/* ACPI_RESOURCE builder helpers */
+#define MAKE_IRQ(Resource, _DescriptorLength, _Triggering, _Polarity, 
_Shareable, _WakeCapable) \
+    do {                                                                       
                 \
+    Resource->Data.Irq.DescriptorLength = _DescriptorLength;                   
                 \
+    Resource->Data.Irq.Triggering = _Triggering;                               
                 \
+    Resource->Data.Irq.Polarity = _Polarity;                                   
                 \
+    Resource->Data.Irq.Shareable = _Shareable;                                 
                 \
+    Resource->Data.Irq.WakeCapable = _WakeCapable;                             
                 \
+    } while (0)
+
+/* IO_RESOURCE_DESCRIPTOR expectations */
+#define expect_irq(Desc, ExpectedOption, ExpectedShare, ExpectedMin, 
ExpectedMax)                                                       \
+    do {                                                                       
                                                         \
+    ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", 
(Desc)->Option);                                                        \
+    ok((Desc)->Type == CmResourceTypeInterrupt, "Desc->Type = %u\n", 
(Desc)->Type);                                                     \
+    ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = 
%u\n", (Desc)->ShareDisposition);                           \
+    ok((Desc)->u.Interrupt.MinimumVector == ExpectedMin, 
"Desc->u.Interrupt.MinimumVector = %lu\n", (Desc)->u.Interrupt.MinimumVector); \
+    ok((Desc)->u.Interrupt.MaximumVector == ExpectedMax, 
"Desc->u.Interrupt.MaximumVector = %lu\n", (Desc)->u.Interrupt.MaximumVector); \
+    } while (0)
+
+#define expect_port(Desc, ExpectedOption, ExpectedShare, ExpectedLength, 
ExpectedAlign, ExpectedMin, ExpectedMax)                                   \
+    do {                                                                       
                                                                     \
+    ok((Desc)->Option == ExpectedOption, "Desc->Option = %u\n", 
(Desc)->Option);                                                                
    \
+    ok((Desc)->Type == CmResourceTypePort, "Desc->Type = %u\n", (Desc)->Type); 
                                                                     \
+    ok((Desc)->ShareDisposition == ExpectedShare, "Desc->ShareDisposition = 
%u\n", (Desc)->ShareDisposition);                                       \
+    ok((Desc)->u.Port.Length == ExpectedLength, "Desc->u.Port.Length = %lu\n", 
(Desc)->u.Port.Length);                                              \
+    ok((Desc)->u.Port.Alignment == ExpectedAlign, "Desc->u.Port.Alignment = 
%lu\n", (Desc)->u.Port.Alignment);                                      \
+    ok((Desc)->u.Port.MinimumAddress.QuadPart == ExpectedMin, 
"Desc->u.Port.MinimumAddress = 0x%I64x\n", 
(Desc)->u.Port.MinimumAddress.QuadPart);   \
+    ok((Desc)->u.Port.MaximumAddress.QuadPart == ExpectedMax, 
"Desc->u.Port.MaximumAddress = 0x%I64x\n", 
(Desc)->u.Port.MaximumAddress.QuadPart);   \
+    } while (0)
+
+START_TEST(Bus_PDO_QueryResourceRequirements)
+{
+    NTSTATUS Status;
+    PDO_DEVICE_DATA DeviceData;
+    IRP Irp;
+    ACPI_RESOURCE ResourcesBuffer[20];
+    ACPI_RESOURCE *Resource;
+    PIO_RESOURCE_REQUIREMENTS_LIST ReqList;
+    PIO_RESOURCE_LIST ReqList2;
+
+    /* Invalid AcpiHandle */
+    AcpiCallExpected = FALSE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    DeviceData.AcpiHandle = NULL;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
+
+    /* PCI Bus device */
+    AcpiCallExpected = FALSE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0A03\0";
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
+
+    /* PCI Bus device #2 */
+    AcpiCallExpected = FALSE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0A08\0";
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
+
+    /* Empty buffer */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_WAIT_0 + 17, "Status = 0x%lx\n", Status);
+
+    /* Simple single-resource list */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    Irp.IoStatus.Information = 0;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Resource = ResourcesBuffer;
+    Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
+    Resource->Length = sizeof(*Resource);
+    MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, 
ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
+    Resource->Data.Irq.InterruptCount = 1;
+    Resource->Data.Irq.Interrupts[0] = 7;
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
+    Resource->Length = 0;
+    Resource++;
+    PossibleBuffer.Pointer = ResourcesBuffer;
+    PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
+    ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", 
Irp.IoStatus.Status);
+    ReqList = (PVOID)Irp.IoStatus.Information;
+    ok(ReqList != NULL, "ReqList is NULL\n");
+    if (ReqList == NULL)
+    {
+        skip("No ReqList\n");
+        return;
+    }
+    ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", 
ReqList->InterfaceType);
+    ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
+    ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
+    ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", 
ReqList->AlternativeLists);
+    ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", 
ReqList->List[0].Version);
+    ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", 
ReqList->List[0].Revision);
+    ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", 
ReqList->List[0].Count);
+    expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDeviceExclusive, 7, 7);
+    ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
+    ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - 
(ULONG_PTR)ReqList);
+    ExFreePoolWithTag(ReqList, 'RpcA');
+
+    /* Two IRQs */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    Irp.IoStatus.Information = 0;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Resource = ResourcesBuffer;
+    Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
+    Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + 
FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]);
+    MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, 
ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
+    Resource->Data.Irq.InterruptCount = 2;
+    Resource->Data.Irq.Interrupts[0] = 3;
+    Resource->Data.Irq.Interrupts[1] = 7;
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
+    Resource->Length = 0;
+    Resource++;
+    PossibleBuffer.Pointer = ResourcesBuffer;
+    PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
+    ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", 
Irp.IoStatus.Status);
+    ReqList = (PVOID)Irp.IoStatus.Information;
+    ok(ReqList != NULL, "ReqList is NULL\n");
+    if (ReqList == NULL)
+    {
+        skip("No ReqList\n");
+        return;
+    }
+    ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", 
ReqList->InterfaceType);
+    ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
+    ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
+    ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", 
ReqList->AlternativeLists);
+    ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", 
ReqList->List[0].Version);
+    ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", 
ReqList->List[0].Revision);
+    ok(ReqList->List[0].Count == 2, "List[0].Count = %lu\n", 
ReqList->List[0].Count);
+    expect_irq(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDeviceExclusive, 3, 3);
+    expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 7, 7);
+    ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
+    ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[2] - 
(ULONG_PTR)ReqList);
+    ExFreePoolWithTag(ReqList, 'RpcA');
+
+    /* Port */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    Irp.IoStatus.Information = 0;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Resource = ResourcesBuffer;
+    Resource->Type = ACPI_RESOURCE_TYPE_IO;
+    Resource->Length = sizeof(*Resource);
+    Resource->Data.Io.IoDecode = ACPI_DECODE_16;
+    Resource->Data.Io.Alignment = 8;
+    Resource->Data.Io.AddressLength = 8;
+    Resource->Data.Io.Minimum = 0x3F8;
+    Resource->Data.Io.Maximum = 0x3F8;
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
+    Resource->Length = 0;
+    Resource++;
+    PossibleBuffer.Pointer = ResourcesBuffer;
+    PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
+    ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", 
Irp.IoStatus.Status);
+    ReqList = (PVOID)Irp.IoStatus.Information;
+    ok(ReqList != NULL, "ReqList is NULL\n");
+    if (ReqList == NULL)
+    {
+        skip("No ReqList\n");
+        return;
+    }
+    ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", 
ReqList->InterfaceType);
+    ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
+    ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
+    ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", 
ReqList->AlternativeLists);
+    ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", 
ReqList->List[0].Version);
+    ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", 
ReqList->List[0].Revision);
+    ok(ReqList->List[0].Count == 1, "List[0].Count = %lu\n", 
ReqList->List[0].Count);
+    expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF);
+    ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
+    ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[1] - 
(ULONG_PTR)ReqList);
+    ExFreePoolWithTag(ReqList, 'RpcA');
+
+    /* Port + two IRQs */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    Irp.IoStatus.Information = 0;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Resource = ResourcesBuffer;
+    Resource->Type = ACPI_RESOURCE_TYPE_IO;
+    Resource->Length = sizeof(*Resource);
+    Resource->Data.Io.IoDecode = ACPI_DECODE_16;
+    Resource->Data.Io.Alignment = 8;
+    Resource->Data.Io.AddressLength = 8;
+    Resource->Data.Io.Minimum = 0x3F8;
+    Resource->Data.Io.Maximum = 0x3F8;
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
+    Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + 
FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[2]);
+    MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, 
ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
+    Resource->Data.Irq.InterruptCount = 2;
+    Resource->Data.Irq.Interrupts[0] = 3;
+    Resource->Data.Irq.Interrupts[1] = 7;
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
+    Resource->Length = 0;
+    Resource++;
+    PossibleBuffer.Pointer = ResourcesBuffer;
+    PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
+    ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", 
Irp.IoStatus.Status);
+    ReqList = (PVOID)Irp.IoStatus.Information;
+    ok(ReqList != NULL, "ReqList is NULL\n");
+    if (ReqList == NULL)
+    {
+        skip("No ReqList\n");
+        return;
+    }
+    ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", 
ReqList->InterfaceType);
+    ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
+    ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
+    ok(ReqList->AlternativeLists == 1, "AlternativeLists = %lu\n", 
ReqList->AlternativeLists);
+    ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", 
ReqList->List[0].Version);
+    ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", 
ReqList->List[0].Revision);
+    ok(ReqList->List[0].Count == 3, "List[0].Count = %lu\n", 
ReqList->List[0].Count);
+    expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDriverExclusive, 8, 8, 0x3F8, 0x3FF);
+    expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, 
CmResourceShareDeviceExclusive, 3, 3);
+    expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 7, 7);
+    ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
+    ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList->List[0].Descriptors[3] - 
(ULONG_PTR)ReqList);
+    ExFreePoolWithTag(ReqList, 'RpcA');
+
+    /* Multiple alternatives for ports + IRQs (VMware COM port, simplified) */
+    AcpiCallExpected = TRUE;
+    Irp.IoStatus.Status = STATUS_WAIT_0 + 17;
+    Irp.IoStatus.Information = 0;
+    DeviceData.AcpiHandle = CorrectHandle;
+    DeviceData.HardwareIDs = L"PNP0501\0";
+    Resource = ResourcesBuffer;
+    Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT;
+    Resource->Length = sizeof(*Resource);
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_IO;
+    Resource->Length = sizeof(*Resource);
+    Resource->Data.Io.IoDecode = ACPI_DECODE_16;
+    Resource->Data.Io.Alignment = 8;
+    Resource->Data.Io.AddressLength = 8;
+    Resource->Data.Io.Minimum = 0x3E8;
+    Resource->Data.Io.Maximum = 0x3E8;
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
+    Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + 
FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]);
+    MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, 
ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
+    Resource->Data.Irq.InterruptCount = 5;
+    Resource->Data.Irq.Interrupts[0] = 3;
+    Resource->Data.Irq.Interrupts[1] = 4;
+    Resource->Data.Irq.Interrupts[2] = 5;
+    Resource->Data.Irq.Interrupts[3] = 6;
+    Resource->Data.Irq.Interrupts[4] = 7;
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_START_DEPENDENT;
+    Resource->Length = sizeof(*Resource);
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_IO;
+    Resource->Length = sizeof(*Resource);
+    Resource->Data.Io.IoDecode = ACPI_DECODE_16;
+    Resource->Data.Io.Alignment = 8;
+    Resource->Data.Io.AddressLength = 8;
+    Resource->Data.Io.Minimum = 0x2E8;
+    Resource->Data.Io.Maximum = 0x2E8;
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_IRQ;
+    Resource->Length = FIELD_OFFSET(ACPI_RESOURCE, Data) + 
FIELD_OFFSET(ACPI_RESOURCE_IRQ, Interrupts[5]);
+    MAKE_IRQ(Resource, 3, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH, 
ACPI_EXCLUSIVE, ACPI_NOT_WAKE_CAPABLE);
+    Resource->Data.Irq.InterruptCount = 5;
+    Resource->Data.Irq.Interrupts[0] = 3;
+    Resource->Data.Irq.Interrupts[1] = 4;
+    Resource->Data.Irq.Interrupts[2] = 5;
+    Resource->Data.Irq.Interrupts[3] = 6;
+    Resource->Data.Irq.Interrupts[4] = 7;
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_DEPENDENT;
+    Resource->Length = sizeof(*Resource);
+
+    Resource = ACPI_NEXT_RESOURCE(Resource);
+    Resource->Type = ACPI_RESOURCE_TYPE_END_TAG;
+    Resource->Length = 0;
+    Resource++;
+    PossibleBuffer.Pointer = ResourcesBuffer;
+    PossibleBuffer.Length = (ULONG_PTR)Resource - (ULONG_PTR)ResourcesBuffer;
+    Status = Bus_PDO_QueryResourceRequirements(&DeviceData, &Irp);
+    ok(Status == STATUS_SUCCESS, "Status = 0x%lx\n", Status);
+    ok(Irp.IoStatus.Status == STATUS_WAIT_0 + 17, "IoStatus.Status = 0x%lx\n", 
Irp.IoStatus.Status);
+    ReqList = (PVOID)Irp.IoStatus.Information;
+    ok(ReqList != NULL, "ReqList is NULL\n");
+    if (ReqList == NULL)
+    {
+        skip("No ReqList\n");
+        return;
+    }
+    ok(ReqList->InterfaceType == Internal, "InterfaceType = %u\n", 
ReqList->InterfaceType);
+    ok(ReqList->BusNumber == 0, "BusNumber = %lu\n", ReqList->BusNumber);
+    ok(ReqList->SlotNumber == 0, "SlotNumber = %lu\n", ReqList->SlotNumber);
+    ok(ReqList->AlternativeLists == 2, "AlternativeLists = %lu\n", 
ReqList->AlternativeLists);
+    ok(ReqList->List[0].Version == 1, "List[0].Version = %u\n", 
ReqList->List[0].Version);
+    ok(ReqList->List[0].Revision == 1, "List[0].Revision = %u\n", 
ReqList->List[0].Revision);
+    ok(ReqList->List[0].Count == 6, "List[0].Count = %lu\n", 
ReqList->List[0].Count);
+    expect_port(&ReqList->List[0].Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDriverExclusive, 8, 8, 0x3E8, 0x3EF);
+    expect_irq(&ReqList->List[0].Descriptors[1], IO_RESOURCE_PREFERRED, 
CmResourceShareDeviceExclusive, 3, 3);
+    expect_irq(&ReqList->List[0].Descriptors[2], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 4, 4);
+    expect_irq(&ReqList->List[0].Descriptors[3], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 5, 5);
+    expect_irq(&ReqList->List[0].Descriptors[4], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 6, 6);
+    expect_irq(&ReqList->List[0].Descriptors[5], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 7, 7);
+    ReqList2 = (PVOID)&ReqList->List[0].Descriptors[6];
+    if (ReqList->ListSize > (ULONG_PTR)ReqList2 - (ULONG_PTR)ReqList)
+    {
+        ok(ReqList2->Version == 1, "List[1].Version = %u\n", 
ReqList->List[0].Version);
+        ok(ReqList2->Revision == 1, "List[1].Revision = %u\n", 
ReqList->List[0].Revision);
+        ok(ReqList2->Count == 6, "List[1].Count = %lu\n", 
ReqList->List[0].Count);
+        expect_port(&ReqList2->Descriptors[0], IO_RESOURCE_PREFERRED, 
CmResourceShareDriverExclusive, 8, 8, 0x2E8, 0x2EF);
+        expect_irq(&ReqList2->Descriptors[1], IO_RESOURCE_PREFERRED, 
CmResourceShareDeviceExclusive, 3, 3);
+        expect_irq(&ReqList2->Descriptors[2], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 4, 4);
+        expect_irq(&ReqList2->Descriptors[3], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 5, 5);
+        expect_irq(&ReqList2->Descriptors[4], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 6, 6);
+        expect_irq(&ReqList2->Descriptors[5], IO_RESOURCE_ALTERNATIVE, 
CmResourceShareDeviceExclusive, 7, 7);
+    }
+    ok_int(ReqList->ListSize, GetPoolAllocSize(ReqList));
+    ok_int(ReqList->ListSize, (ULONG_PTR)&ReqList2->Descriptors[6] - 
(ULONG_PTR)ReqList);
+    ExFreePoolWithTag(ReqList, 'RpcA');
+}
diff --git a/modules/rostests/apitests/acpi/CMakeLists.txt 
b/modules/rostests/apitests/acpi/CMakeLists.txt
new file mode 100644
index 00000000000..8092262c0ff
--- /dev/null
+++ b/modules/rostests/apitests/acpi/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/drivers/bus/acpi/acpica/include)
+
+list(APPEND SOURCE
+    Bus_PDO_QueryResourceRequirements.c
+    testlist.c)
+
+add_executable(acpi_apitest ${SOURCE})
+set_module_type(acpi_apitest win32cui)
+add_importlibs(acpi_apitest msvcrt kernel32 ntdll)
+
+add_rostests_file(TARGET acpi_apitest)
diff --git a/modules/rostests/apitests/acpi/testlist.c 
b/modules/rostests/apitests/acpi/testlist.c
new file mode 100644
index 00000000000..e5fb3bc6e41
--- /dev/null
+++ b/modules/rostests/apitests/acpi/testlist.c
@@ -0,0 +1,10 @@
+#define STANDALONE
+#include <apitest.h>
+
+extern void func_Bus_PDO_QueryResourceRequirements(void);
+
+const struct test winetest_testlist[] =
+{
+    { "Bus_PDO_QueryResourceRequirements", 
func_Bus_PDO_QueryResourceRequirements },
+    { 0, 0 }
+};

Reply via email to