https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9bcd83507467c4c56195e…
commit 9bcd83507467c4c56195e5a342e0d60ff07a2068
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Tue Aug 6 19:54:40 2019 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
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 (thomas.faber(a)reactos.org)
+ */
+
+#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 }
+};