From 3ee036245bfb8de6a1432bc03ffc641b00ee197c Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 21 Sep 2021 18:05:13 +0300 Subject: [PATCH] gdi32: Add a semi-stub for D3DKMTOpenAdapterFromDeviceName(). Fixes non functional setting page in Resident Evil Village. Signed-off-by: Paul Gofman Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- .../api-ms-win-dx-d3dkmt-l1-1-0.spec | 2 +- dlls/gdi32/driver.c | 20 ++++ dlls/gdi32/gdi32.spec | 1 + dlls/gdi32/tests/Makefile.in | 2 +- dlls/gdi32/tests/driver.c | 99 +++++++++++++++++++ include/ntgdi.h | 1 + 6 files changed, 123 insertions(+), 2 deletions(-) diff --git a/dlls/api-ms-win-dx-d3dkmt-l1-1-0/api-ms-win-dx-d3dkmt-l1-1-0.spec b/dlls/api-ms-win-dx-d3dkmt-l1-1-0/api-ms-win-dx-d3dkmt-l1-1-0.spec index 609f24fcfde..3c5c8d9b670 100644 --- a/dlls/api-ms-win-dx-d3dkmt-l1-1-0/api-ms-win-dx-d3dkmt-l1-1-0.spec +++ b/dlls/api-ms-win-dx-d3dkmt-l1-1-0/api-ms-win-dx-d3dkmt-l1-1-0.spec @@ -45,7 +45,7 @@ @ stub D3DKMTInvalidateActiveVidPn @ stub D3DKMTLock @ stub D3DKMTOfferAllocations -@ stub D3DKMTOpenAdapterFromDeviceName +@ stdcall D3DKMTOpenAdapterFromDeviceName(ptr) gdi32.D3DKMTOpenAdapterFromDeviceName @ stdcall D3DKMTOpenAdapterFromGdiDisplayName(ptr) gdi32.D3DKMTOpenAdapterFromGdiDisplayName @ stdcall D3DKMTOpenAdapterFromHdc(ptr) gdi32.D3DKMTOpenAdapterFromHdc @ stub D3DKMTOpenKeyedMutex diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index f4a9b09eae5..09e369bf27f 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -989,6 +989,26 @@ NTSTATUS WINAPI NtGdiDdDDICloseAdapter( const D3DKMT_CLOSEADAPTER *desc ) return status; } +/****************************************************************************** + * NtGdiDdDDIOpenAdapterFromDeviceName (win32u.@) + */ +NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc ) +{ + D3DKMT_OPENADAPTERFROMLUID desc_luid; + NTSTATUS status; + + FIXME( "desc %p stub.\n", desc ); + + if (!desc || !desc->pDeviceName) return STATUS_INVALID_PARAMETER; + + memset( &desc_luid, 0, sizeof( desc_luid )); + if ((status = NtGdiDdDDIOpenAdapterFromLuid( &desc_luid ))) return status; + + desc->AdapterLuid = desc_luid.AdapterLuid; + desc->hAdapter = desc_luid.hAdapter; + return STATUS_SUCCESS; +} + /****************************************************************************** * NtGdiDdDDIOpenAdapterFromLuid (win32u.@) */ diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 6dbc8a9bf12..94a5cefdfa4 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) NtGdiDdDDIOpenAdapterFromDeviceName @ stdcall D3DKMTOpenAdapterFromGdiDisplayName(ptr) @ stdcall D3DKMTOpenAdapterFromHdc(ptr) NtGdiDdDDIOpenAdapterFromHdc @ stdcall D3DKMTOpenAdapterFromLuid(ptr) NtGdiDdDDIOpenAdapterFromLuid 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..54144c44e1c 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,97 @@ static void test_D3DKMTCheckOcclusion(void) DestroyWindow(hwnd); } +static void test_D3DKMTOpenAdapterFromDeviceName_deviface(const GUID *devinterface_guid, + NTSTATUS expected_status, BOOL todo) +{ + 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 (SetupDiEnumDeviceInterfaces(set, NULL, devinterface_guid, i, &iface)) + { + ret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, + sizeof(iface_detail_buffer), NULL, &device_data ); + ok(ret, "Got unexpected ret %d, GetLastError() %u.\n", ret, GetLastError()); + + status = pD3DKMTOpenAdapterFromDeviceName(&device_name); + todo_wine_if(todo) 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 %d, GetLastError() %u.\n", + ret, GetLastError()); + + if (ret) + { + ret = RtlEqualLuid( &luid, &device_name.AdapterLuid); + todo_wine 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"); + + SetupDiDestroyDeviceInfoList( set ); +} + +static void test_D3DKMTOpenAdapterFromDeviceName(void) +{ + D3DKMT_OPENADAPTERFROMDEVICENAME device_name; + NTSTATUS status; + + /* Make sure display devices are initialized. */ + SendMessageW(GetDesktopWindow(), WM_NULL, 0, 0); + + status = pD3DKMTOpenAdapterFromDeviceName(NULL); + if (status == STATUS_PROCEDURE_NOT_FOUND) + { + win_skip("D3DKMTOpenAdapterFromDeviceName() 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(&device_name); + 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, TRUE); + winetest_pop_context(); + + winetest_push_context("GUID_DISPLAY_DEVICE_ARRIVAL"); + test_D3DKMTOpenAdapterFromDeviceName_deviface(&GUID_DISPLAY_DEVICE_ARRIVAL, STATUS_SUCCESS, FALSE); + winetest_pop_context(); +} + START_TEST(driver) { HMODULE gdi32 = GetModuleHandleA("gdi32.dll"); @@ -799,6 +896,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 +912,7 @@ START_TEST(driver) test_D3DKMTCheckVidPnExclusiveOwnership(); test_D3DKMTSetVidPnSourceOwner(); test_D3DKMTCheckOcclusion(); + test_D3DKMTOpenAdapterFromDeviceName(); FreeLibrary(dwmapi); } diff --git a/include/ntgdi.h b/include/ntgdi.h index e1f31a6bb9d..05fe0191f39 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -442,6 +442,7 @@ NTSTATUS WINAPI NtGdiDdDDIDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY NTSTATUS WINAPI NtGdiDdDDIDestroyDevice( const D3DKMT_DESTROYDEVICE *desc ); NTSTATUS WINAPI NtGdiDdDDIEscape( const D3DKMT_ESCAPE *desc ); NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromHdc( D3DKMT_OPENADAPTERFROMHDC *desc ); +NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromDeviceName( D3DKMT_OPENADAPTERFROMDEVICENAME *desc ); NTSTATUS WINAPI NtGdiDdDDIOpenAdapterFromLuid( D3DKMT_OPENADAPTERFROMLUID *desc ); NTSTATUS WINAPI NtGdiDdDDIQueryStatistics( D3DKMT_QUERYSTATISTICS *stats ); NTSTATUS WINAPI NtGdiDdDDISetQueuedLimit( D3DKMT_SETQUEUEDLIMIT *desc );