[PATCH 9/9] setupapi/tests: properties and enumerators for display devices
Donat Enikeev
donat at enikeev.net
Mon Apr 24 15:53:41 CDT 2017
Signed-off-by: Donat Enikeev <donat at enikeev.net>
---
dlls/setupapi/tests/devinst.c | 211 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 211 insertions(+)
diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
index 6ca0e92..0fc99b8 100644
--- a/dlls/setupapi/tests/devinst.c
+++ b/dlls/setupapi/tests/devinst.c
@@ -28,6 +28,8 @@
#include "winreg.h"
#include "guiddef.h"
#include "setupapi.h"
+#include "initguid.h"
+#include "devguid.h"
#include "wine/test.h"
@@ -61,6 +63,8 @@ static BOOL (WINAPI *pSetupDiGetDeviceRegistryPropertyW)(HDEVINFO, PSP_DEVIN
static BOOL (WINAPI *pSetupDiRemoveDevice)(HDEVINFO, PSP_DEVINFO_DATA);
static BOOL (WINAPI *pSetupDiRemoveDeviceInterface)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA);
static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
+static BOOL (WINAPI *pEnumDisplayDevicesA)(LPCSTR,DWORD,LPDISPLAY_DEVICEA,DWORD);
+static BOOL (WINAPI *pEnumDisplayDevicesW)(LPCWSTR,DWORD,LPDISPLAY_DEVICEW,DWORD);
/* This is a unique guid for testing purposes */
static GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04,0x00,0x11,0x95,0x5c,0x2b,0xdb}};
@@ -69,6 +73,7 @@ static void init_function_pointers(void)
{
HMODULE hSetupAPI = GetModuleHandleA("setupapi.dll");
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
+ HMODULE hUser32 = GetModuleHandleA("user32.dll");
pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA");
pSetupDiCreateDeviceInfoW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoW");
@@ -97,6 +102,8 @@ static void init_function_pointers(void)
pSetupDiRemoveDeviceInterface = (void *)GetProcAddress(hSetupAPI, "SetupDiRemoveDeviceInterface");
pSetupDiRemoveDevice = (void *)GetProcAddress(hSetupAPI, "SetupDiRemoveDevice");
pIsWow64Process = (void *)GetProcAddress(hKernel32, "IsWow64Process");
+ pEnumDisplayDevicesA = (void *)GetProcAddress(hUser32, "EnumDisplayDevicesA");
+ pEnumDisplayDevicesW = (void *)GetProcAddress(hUser32, "EnumDisplayDevicesW");
}
static LSTATUS devinst_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
@@ -1347,6 +1354,208 @@ static void testSetupDiGetINFClassA(void)
}
}
+static BOOL check_driver_date(const char *driver, DWORD devnum)
+{
+ const SYSTEMTIME date2000_01_01 = {2000, 1, 6, 1, 0, 0, 0, 0};
+ const char class_path[] = "System\\CurrentControlSet\\Control\\Class\\%s";
+ const char driver_date_data[] = "DriverDateData";
+ char driver_path[MAX_PATH];
+ HKEY key;
+ DWORD type, cb;
+ FILETIME driver_date, cmp_date;
+ LONG l;
+
+ sprintf(driver_path, class_path, driver);
+ l = RegOpenKeyExA(HKEY_LOCAL_MACHINE, driver_path, 0, KEY_READ, &key);
+ ok(!l, "Failed to open driver path (%s) in registry for device %d: %08x\n", driver_path, devnum, GetLastError());
+ if (l) return FALSE;
+
+ cb = sizeof(driver_date);
+ l = RegQueryValueExA(key, driver_date_data, 0, &type, (PBYTE)&driver_date, &cb);
+ ok(!l && type == REG_BINARY, "Failed to get %s binary value at %s of device %d: %08x\n", driver_date_data, driver_path, devnum, GetLastError());
+ if (l) return FALSE;
+
+ RegCloseKey(key);
+
+ ok(cb==sizeof(driver_date), "Unexpected size of data in buffer.\n");
+ if (cb==sizeof(driver_date))
+ {
+ SystemTimeToFileTime(&date2000_01_01, &cmp_date);
+ l = CompareFileTime(&driver_date, &cmp_date);
+ ok (l == 1, "Unexpectly old driver date at %s of device %d\n", driver_path, devnum);
+ if (l == 1)
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+static void testDisplayDevsPropertiesA(void)
+{
+ const char displ_class_guid[] = "{4d36e968-e325-11ce-bfc1-08002be10318}";
+ const char displ_class[] = "Display";
+
+ SP_DEVINFO_DATA devinfo;
+ DISPLAY_DEVICEA disp;
+ HDEVINFO set;
+ BOOL ret;
+ DWORD devnum = -1;
+
+ if (!pEnumDisplayDevicesA)
+ {
+ win_skip("EnumDisplayDevicesA() is not available\n");
+ return;
+ }
+
+ disp.cb = sizeof(disp);
+ SetLastError(0xdeadbeef);
+ while (pEnumDisplayDevicesA(NULL, ++devnum, &disp, 0))
+ {
+ if (disp.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER
+ || !(disp.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue;
+
+ set = pSetupDiGetClassDevsA(&GUID_DEVCLASS_DISPLAY, disp.DeviceID, 0, DIGCF_PRESENT);
+ ok(set != INVALID_HANDLE_VALUE
+ /* wxppro */ || GetLastError() == ERROR_INVALID_DATA ,
+ "SetupDiGetClassDevsA failed for device %d (%s, state %08x): %08x\n",
+ devnum, disp.DeviceID, disp.StateFlags, GetLastError());
+
+ if (set == INVALID_HANDLE_VALUE) continue;
+
+ devinfo.cbSize = sizeof(devinfo);
+ ret = pSetupDiEnumDeviceInfo(set, 0, &devinfo);
+ ok(ret, "SetupDiEnumDeviceInfo failed for device %d: %08x\n", devnum, GetLastError());
+ if (ret)
+ {
+ char buffer[MAX_PATH];
+
+ ok(IsEqualGUID(&devinfo.ClassGuid,&GUID_DEVCLASS_DISPLAY),
+ "Expected display GUID in SP_DEVINFO_DATA for device %d\n", devnum);
+
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devinfo,
+ SPDRP_CLASSGUID, NULL, (PBYTE)buffer, MAX_PATH, NULL);
+ ok(ret, "Failed to get CLASSGUID property for device %d: %08x\n", devnum, GetLastError());
+ if (ret)
+ ok(!lstrcmpiA((LPSTR)buffer, displ_class_guid),
+ "Unexpected GUID value (%s) for device %d: %s\n", buffer, devnum, buffer);
+
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devinfo,
+ SPDRP_CLASS, NULL, (PBYTE)buffer, MAX_PATH, NULL);
+ todo_wine ok(ret, "Failed to get CLASS property for device %d: %08x\n", devnum, GetLastError());
+ if (ret)
+ ok(!lstrcmpiA((LPSTR)buffer, displ_class),
+ "Unexpected CLASS value (%s) for device %d: %s\n", buffer, devnum, buffer);
+
+ ret = pSetupDiGetDeviceRegistryPropertyA(set, &devinfo,
+ SPDRP_DRIVER, NULL, (PBYTE)buffer, MAX_PATH, NULL);
+ ok(ret, "Failed to get DRIVER property for device %d: %08x\n", devnum, GetLastError());
+ if (ret)
+ check_driver_date(buffer, devnum);
+ }
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+
+ if (!devnum)
+ skip("No display device available for the test: %08x\n", GetLastError());
+}
+
+static const struct
+{
+ const GUID *classguid;
+ WCHAR enumerator[10]; /* {0} -> use actual display's DeviceID as enumerator, eg PCI\\DEV0000&VEN0000 */
+ DWORD flags;
+ BOOL expect_set;
+ int guid_in_set;
+} displ_enum_tests[] = {
+ { &GUID_DEVCLASS_DISPLAY, {'P','C','I',0}, 0, TRUE, -1 },
+ { &GUID_DEVCLASS_DISPLAY, {'P','C','I','\\','B','O','G','U','S',0}, DIGCF_PRESENT, TRUE, 0 },
+ { NULL, {'P','C','I','\\','B','O','G','U','S',0}, DIGCF_PRESENT | DIGCF_ALLCLASSES, TRUE, 0 },
+ { NULL, {'P','C','I',0}, DIGCF_PRESENT | DIGCF_ALLCLASSES, TRUE, -1 },
+ { NULL, {'P','C','I',0}, DIGCF_PRESENT, FALSE, 0 },
+ { &GUID_DEVCLASS_DISPLAY, {0}, DIGCF_PRESENT, TRUE, -1},
+ { NULL, {0}, DIGCF_PRESENT | DIGCF_ALLCLASSES, TRUE, -1},
+ { NULL, {0}, DIGCF_PRESENT, FALSE, 0},
+ { &GUID_DEVCLASS_DISPLAY, {'I','D','E',0}, 0, TRUE, 0 },
+ { &GUID_DEVCLASS_FLOPPYDISK, {'P','C','I',0}, 0 , TRUE, 0 },
+ { &GUID_DEVCLASS_FLOPPYDISK, {0}, 0, TRUE, 0 },
+};
+
+static void testDisplayDevsEnumeratorsW(void)
+{
+ DISPLAY_DEVICEW disp;
+ HDEVINFO set;
+ BOOL ret;
+ DWORD devnum = -1;
+ int i;
+
+ if (!pEnumDisplayDevicesW)
+ {
+ win_skip("EnumDisplayDevicesW() is not available\n");
+ return;
+ }
+
+ disp.cb = sizeof(disp);
+ SetLastError(0xdeadbeef);
+ while (pEnumDisplayDevicesW(NULL, ++devnum, &disp, 0))
+ {
+ if (disp.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER
+ || !(disp.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue;
+
+ for (i = 0; i < sizeof(displ_enum_tests) / sizeof(displ_enum_tests[0]); i++)
+ {
+ DWORD member_idx;
+ BOOL displ_guid_found;
+
+ set = pSetupDiGetClassDevsW(displ_enum_tests[i].classguid,
+ displ_enum_tests[i].enumerator[0] ? displ_enum_tests[i].enumerator : NULL,
+ 0, displ_enum_tests[i].flags);
+
+ if (set == INVALID_HANDLE_VALUE)
+ {
+ ok(!displ_enum_tests[i].expect_set
+ /* wxppro .. w7pro */ || GetLastError() == ERROR_INVALID_DATA,
+ "Unexpected set for device %d (state %08x) at %d: %08x\n",
+ devnum, disp.StateFlags, i, GetLastError());
+ continue;
+ }
+
+ member_idx = 0;
+ displ_guid_found = FALSE;
+ do
+ {
+ SP_DEVINFO_DATA devinfo;
+
+ devinfo.cbSize = sizeof(devinfo);
+ ret = pSetupDiEnumDeviceInfo(set, member_idx, &devinfo);
+ ok (ret || GetLastError() == ERROR_NO_MORE_ITEMS,
+ "Failed to get %d member of deivce %d info set at %d: %08x\n",
+ member_idx, devnum, i, GetLastError());
+
+ if (ret && IsEqualGUID(&devinfo.ClassGuid,&GUID_DEVCLASS_DISPLAY))
+ {
+ displ_guid_found = TRUE;
+ break;
+ }
+ member_idx++;
+ } while (ret);
+
+ ok( displ_guid_found || !displ_enum_tests[i].guid_in_set
+ /* Some tests fail on testbot's wxppro VM, skipping it */ ||
+ displ_enum_tests[i].guid_in_set == -1,
+ "No display GUID found in device %d set among %d entries at %d\n", devnum, member_idx-1, i);
+
+ if (!displ_guid_found && displ_enum_tests[i].guid_in_set == -1)
+ win_skip("No display GUID found in device %d set among %d entries at %d;"
+ " expected for some wxppro VM only\n",devnum, member_idx-1, i);
+
+ pSetupDiDestroyDeviceInfoList(set);
+ }
+ }
+ if (!devnum)
+ skip("No display device available for the test: %08x\n", GetLastError());
+}
+
START_TEST(devinst)
{
HKEY hkey;
@@ -1384,4 +1593,6 @@ START_TEST(devinst)
testDeviceRegistryPropertyA();
testDeviceRegistryPropertyW();
testSetupDiGetINFClassA();
+ testDisplayDevsPropertiesA();
+ testDisplayDevsEnumeratorsW();
}
--
2.7.4
More information about the wine-patches
mailing list