Fixes non functional setting page in Resident Evil Village.
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/gdi32/gdi32.spec | 1 +
dlls/gdi32/objects.c | 65 ++++++++++++++++++++++
dlls/gdi32/tests/Makefile.in | 2 +-
dlls/gdi32/tests/driver.c | 103 +++++++++++++++++++++++++++++++++++
4 files changed, 170 insertions(+), 1 deletion(-)
diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec
index 6dbc8a9bf12..46534796317 100644
--- a/dlls/gdi32/gdi32.spec
+++ b/dlls/gdi32/gdi32.spec
@@ -80,6 +80,7 @@
@ stdcall D3DKMTDestroyDCFromMemory(ptr) NtGdiDdDDIDestroyDCFromMemory
@ stdcall D3DKMTDestroyDevice(ptr) NtGdiDdDDIDestroyDevice
@ stdcall D3DKMTEscape(ptr) NtGdiDdDDIEscape
+@ stdcall D3DKMTOpenAdapterFromDeviceName(ptr)
@ stdcall D3DKMTOpenAdapterFromGdiDisplayName(ptr)
@ stdcall D3DKMTOpenAdapterFromHdc(ptr) NtGdiDdDDIOpenAdapterFromHdc
@ stdcall D3DKMTOpenAdapterFromLuid(ptr) NtGdiDdDDIOpenAdapterFromLuid
diff --git a/dlls/gdi32/objects.c b/dlls/gdi32/objects.c
index 7f6893f0952..a4ae33442d3 100644
--- a/dlls/gdi32/objects.c
+++ b/dlls/gdi32/objects.c
@@ -30,6 +30,7 @@
#include "initguid.h"
#include "devguid.h"
#include "setupapi.h"
+#include "ntddvdeo.h"
#include "wine/rbtree.h"
#include "wine/debug.h"
@@ -889,6 +890,70 @@ static void release_display_device_init_mutex( HANDLE mutex )
CloseHandle( mutex );
}
+/******************************************************************************
+ * D3DKMTOpenAdapterFromDeviceName (GDI32.@)
+ */
+NTSTATUS WINAPI D3DKMTOpenAdapterFromDeviceName(D3DKMT_OPENADAPTERFROMDEVICENAME *device_name)
+{
+ static const GUID *iface_guid = &GUID_DISPLAY_DEVICE_ARRIVAL;
+ SP_DEVICE_INTERFACE_DATA iface_data = {sizeof(iface_data)};
+ SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail_data;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ NTSTATUS status = STATUS_INVALID_PARAMETER;
+ D3DKMT_OPENADAPTERFROMLUID luid_desc;
+ WCHAR iface_detail_buffer[256];
+ BOOL found = FALSE;
+ DEVPROPTYPE type;
+ unsigned int i;
+ HDEVINFO set;
+ HANDLE mutex;
+
+ TRACE( "device_name %p.\n", device_name );
+
+ if (!device_name) return STATUS_INVALID_PARAMETER;
+
+ TRACE("device path %s.\n", debugstr_w( device_name->pDeviceName ));
+
+ mutex = get_display_device_init_mutex();
+
+ set = SetupDiGetClassDevsW( iface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
+ iface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer;
+ iface_detail_data->cbSize = sizeof(*iface_detail_data);
+
+ for (i = 0; SetupDiEnumDeviceInfo( set, i, &device_data ); ++i)
+ {
+ if (!SetupDiEnumDeviceInterfaces( set, &device_data, iface_guid, 0, &iface_data )
+ || !SetupDiGetDeviceInterfaceDetailW( set, &iface_data, iface_detail_data,
+ sizeof(iface_detail_buffer), NULL, &device_data ))
+ {
+ ERR( "Could not get interface detail, iface %u.\n", i );
+ continue;
+ }
+ if (lstrcmpiW( device_name->pDeviceName, iface_detail_data->DevicePath )) continue;
+
+ if (SetupDiGetDevicePropertyW( set, &device_data, &DEVPROPKEY_GPU_LUID, &type,
+ (BYTE *)&luid_desc.AdapterLuid,
+ sizeof( luid_desc.AdapterLuid ), NULL, 0))
+ found = TRUE;
+ else
+ ERR( "Could not get luid.\n" );
+
+ break;
+ }
+
+ SetupDiDestroyDeviceInfoList( set );
+
+ if (found && !(status = NtGdiDdDDIOpenAdapterFromLuid( &luid_desc )))
+ {
+ device_name->hAdapter = luid_desc.hAdapter;
+ device_name->AdapterLuid = luid_desc.AdapterLuid;
+ } else WARN( "Device %s not found.\n", debugstr_w(device_name->pDeviceName ));
+
+ release_display_device_init_mutex( mutex );
+
+ return status;
+}
+
/***********************************************************************
* D3DKMTOpenAdapterFromGdiDisplayName (GDI32.@)
*/
diff --git a/dlls/gdi32/tests/Makefile.in b/dlls/gdi32/tests/Makefile.in
index 876f6a376a2..3eb478ff765 100644
--- a/dlls/gdi32/tests/Makefile.in
+++ b/dlls/gdi32/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = gdi32.dll
-IMPORTS = user32 gdi32 advapi32
+IMPORTS = setupapi user32 gdi32 advapi32
C_SRCS = \
bitmap.c \
diff --git a/dlls/gdi32/tests/driver.c b/dlls/gdi32/tests/driver.c
index eb0da18b32e..c20f8088d9c 100644
--- a/dlls/gdi32/tests/driver.c
+++ b/dlls/gdi32/tests/driver.c
@@ -29,16 +29,22 @@
#include "winternl.h"
#include "dwmapi.h"
#include "ddk/d3dkmthk.h"
+#include "initguid.h"
+#include "setupapi.h"
+#include "ntddvdeo.h"
#include "wine/test.h"
static const WCHAR display1W[] = L"\\\\.\\DISPLAY1";
+DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
+
static NTSTATUS (WINAPI *pD3DKMTCheckOcclusion)(const D3DKMT_CHECKOCCLUSION *);
static NTSTATUS (WINAPI *pD3DKMTCheckVidPnExclusiveOwnership)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP *);
static NTSTATUS (WINAPI *pD3DKMTCloseAdapter)(const D3DKMT_CLOSEADAPTER *);
static NTSTATUS (WINAPI *pD3DKMTCreateDevice)(D3DKMT_CREATEDEVICE *);
static NTSTATUS (WINAPI *pD3DKMTDestroyDevice)(const D3DKMT_DESTROYDEVICE *);
+static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromDeviceName)(D3DKMT_OPENADAPTERFROMDEVICENAME *);
static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromGdiDisplayName)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME *);
static NTSTATUS (WINAPI *pD3DKMTOpenAdapterFromHdc)(D3DKMT_OPENADAPTERFROMHDC *);
static NTSTATUS (WINAPI *pD3DKMTSetVidPnSourceOwner)(const D3DKMT_SETVIDPNSOURCEOWNER *);
@@ -789,6 +795,101 @@ static void test_D3DKMTCheckOcclusion(void)
DestroyWindow(hwnd);
}
+static void test_D3DKMTOpenAdapterFromDeviceName_deviface(const GUID *devinterface_guid, NTSTATUS expected_status)
+{
+ BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)];
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
+ SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data;
+ D3DKMT_OPENADAPTERFROMDEVICENAME device_name;
+ D3DKMT_CLOSEADAPTER close_adapter_desc;
+ DEVPROPTYPE type;
+ NTSTATUS status;
+ unsigned int i;
+ HDEVINFO set;
+ LUID luid;
+ BOOL ret;
+
+ set = SetupDiGetClassDevsW(devinterface_guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
+ ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevs failed, error %u.\n", GetLastError());
+
+ iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer;
+ iface_data->cbSize = sizeof(*iface_data);
+ device_name.pDeviceName = iface_data->DevicePath;
+
+ i = 0;
+ while ((ret = SetupDiEnumDeviceInfo(set, i, &device_data)))
+ {
+ ret = SetupDiEnumDeviceInterfaces(set, &device_data, devinterface_guid, 0, &iface);
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data,
+ sizeof(iface_detail_buffer), NULL, NULL );
+ ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ status = pD3DKMTOpenAdapterFromDeviceName(&device_name);
+ ok(status == expected_status, "Got status %#x, expected %#x.\n", status, expected_status);
+
+ if (!status)
+ {
+ ret = SetupDiGetDevicePropertyW(set, &device_data, &DEVPROPKEY_GPU_LUID, &type,
+ (BYTE *)&luid, sizeof(luid), NULL, 0);
+ ok(ret || GetLastError() == ERROR_NOT_FOUND, "Got unexpected ret %#x, GetLastError() %u.\n",
+ ret, GetLastError());
+
+ if (ret)
+ {
+ ret = RtlEqualLuid( &luid, &device_name.AdapterLuid);
+ ok(ret, "Luid does not match.\n");
+ }
+ else
+ {
+ skip("Luid not found.\n");
+ }
+
+ close_adapter_desc.hAdapter = device_name.hAdapter;
+ status = pD3DKMTCloseAdapter(&close_adapter_desc);
+ ok(!status, "Got unexpected status %#x.\n", status);
+ }
+ ++i;
+ }
+ if (!i)
+ win_skip("No devices found.\n");
+}
+
+static void test_D3DKMTOpenAdapterFromDeviceName(void)
+{
+ D3DKMT_OPENADAPTERFROMDEVICENAME device_name;
+ NTSTATUS status;
+ HWND hwnd;
+
+ /* Create window to make sure display devices are initialized before the test. */
+ hwnd = CreateWindowA("static", "static1", WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, 0, 0);
+ ok(!!hwnd, "Failed to create window.\n");
+
+ status = pD3DKMTOpenAdapterFromDeviceName(NULL);
+ if (status == STATUS_PROCEDURE_NOT_FOUND)
+ {
+ win_skip("pD3DKMTOpenAdapterFromDeviceName() is not supported.\n");
+ return;
+ }
+ ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
+
+ memset(&device_name, 0, sizeof(device_name));
+ status = pD3DKMTOpenAdapterFromDeviceName(NULL);
+ ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
+
+ winetest_push_context("GUID_DEVINTERFACE_DISPLAY_ADAPTER");
+ test_D3DKMTOpenAdapterFromDeviceName_deviface(&GUID_DEVINTERFACE_DISPLAY_ADAPTER, STATUS_INVALID_PARAMETER);
+ winetest_pop_context();
+
+ winetest_push_context("GUID_DISPLAY_DEVICE_ARRIVAL");
+ test_D3DKMTOpenAdapterFromDeviceName_deviface(&GUID_DISPLAY_DEVICE_ARRIVAL, STATUS_SUCCESS);
+ winetest_pop_context();
+
+ DestroyWindow(hwnd);
+}
+
START_TEST(driver)
{
HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
@@ -799,6 +900,7 @@ START_TEST(driver)
pD3DKMTCloseAdapter = (void *)GetProcAddress(gdi32, "D3DKMTCloseAdapter");
pD3DKMTCreateDevice = (void *)GetProcAddress(gdi32, "D3DKMTCreateDevice");
pD3DKMTDestroyDevice = (void *)GetProcAddress(gdi32, "D3DKMTDestroyDevice");
+ pD3DKMTOpenAdapterFromDeviceName = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromDeviceName");
pD3DKMTOpenAdapterFromGdiDisplayName = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
pD3DKMTOpenAdapterFromHdc = (void *)GetProcAddress(gdi32, "D3DKMTOpenAdapterFromHdc");
pD3DKMTSetVidPnSourceOwner = (void *)GetProcAddress(gdi32, "D3DKMTSetVidPnSourceOwner");
@@ -814,6 +916,7 @@ START_TEST(driver)
test_D3DKMTCheckVidPnExclusiveOwnership();
test_D3DKMTSetVidPnSourceOwner();
test_D3DKMTCheckOcclusion();
+ test_D3DKMTOpenAdapterFromDeviceName();
FreeLibrary(dwmapi);
}
--
2.31.1