[PATCH] gdi32: Implement D3DKMTOpenAdapterFromDeviceName().

Zhiyi Zhang zzhang at codeweavers.com
Fri Sep 17 08:34:58 CDT 2021



On 9/17/21 8:39 PM, Paul Gofman wrote:
> Fixes non functional setting page in Resident Evil Village.
>
> Signed-off-by: Paul Gofman <pgofman at 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;
Not an issue. I would prefer using GUID_DISPLAY_DEVICE_ARRIVAL directly.

> +    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;

Please check and test NULL device_name->pDeviceName as well.

> +
> +    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);
> +
I think you can call SetupDiEnumDeviceInterfaces() directly to enumerate the information set without calling  SetupDiEnumDeviceInfo()

> +    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 ));
Please put curly braces around WARN as well.

> +
> +    release_display_device_init_mutex( mutex );

Call release_display_device_init_mutex() sooner.

> +
> +    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)))
> +    {
Delete this empty line.

> +        ret = SetupDiEnumDeviceInterfaces(set, &device_data, devinterface_guid, 0, &iface);
> +        ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
Use %d to print BOOL.

> +
> +        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");

set is leaked.


> +}
> +
> +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");
Send a WM_NULL to the desktop window should be enough.


> +
> +    status = pD3DKMTOpenAdapterFromDeviceName(NULL);
> +    if (status == STATUS_PROCEDURE_NOT_FOUND)
> +    {
> +        win_skip("pD3DKMTOpenAdapterFromDeviceName() is not supported.\n");

hwnd is leaked.


> +        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);
>  }



More information about the wine-devel mailing list