Wine-Devel
Threads by month
- ----- 2026 -----
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2019
- 66 participants
- 557 discussions
[PATCH v2 6/6] winemac.drv: Use generic EnumDisplayMonitors and GetMonitorInfo.
by Zhiyi Zhang Aug. 28, 2019
by Zhiyi Zhang Aug. 28, 2019
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_display.m | 2 +
dlls/winemac.drv/display.c | 154 +++++---------------------------------
dlls/winemac.drv/macdrv_cocoa.h | 4 +
dlls/winemac.drv/winemac.drv.spec | 2 -
4 files changed, 26 insertions(+), 136 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index f068a8aa3f..7577e6574f 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -649,6 +649,8 @@ int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** new_monitor
strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor");
monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE;
+ monitors[monitor_count].rc_monitor = displays[j].frame;
+ monitors[monitor_count].rc_work = displays[j].work_frame;
monitor_count++;
}
}
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index 236f63d563..cb9f1ebcab 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -53,6 +53,9 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW
/* Wine specific monitor properties */
DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCMONITOR, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 3);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_RCWORK, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 4);
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 5);
static const char initial_mode_key[] = "Initial Display Mode";
static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
@@ -64,6 +67,7 @@ static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
static const WCHAR symbolic_link_valueW[]= {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
static const WCHAR gpu_idW[] = {'G','P','U','I','D',0};
static const WCHAR mointor_id_fmtW[] = {'M','o','n','i','t','o','r','I','D','%','d',0};
+static const WCHAR adapter_name_fmtW[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','%','d',0};
static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
static const WCHAR guid_fmtW[] = {
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
@@ -128,18 +132,6 @@ static CRITICAL_SECTION modes_section = { &critsect_debug, -1, 0, 0, 0, 0 };
static BOOL inited_original_display_mode;
-
-static inline HMONITOR display_id_to_monitor(CGDirectDisplayID display_id)
-{
- return (HMONITOR)(UINT_PTR)display_id;
-}
-
-static inline CGDirectDisplayID monitor_to_display_id(HMONITOR handle)
-{
- return (CGDirectDisplayID)(UINT_PTR)handle;
-}
-
-
static BOOL get_display_device_reg_key(char *key, unsigned len)
{
static const char display_device_guid_prop[] = "__wine_display_device_guid";
@@ -969,76 +961,6 @@ better:
return ret;
}
-
-/***********************************************************************
- * EnumDisplayMonitors (MACDRV.@)
- */
-BOOL CDECL macdrv_EnumDisplayMonitors(HDC hdc, LPRECT rect, MONITORENUMPROC proc, LPARAM lparam)
-{
- struct macdrv_display *displays;
- int num_displays;
- int i;
- BOOL ret = TRUE;
-
- TRACE("%p, %s, %p, %#lx\n", hdc, wine_dbgstr_rect(rect), proc, lparam);
-
- if (hdc)
- {
- POINT origin;
- RECT limit;
-
- if (!GetDCOrgEx(hdc, &origin)) return FALSE;
- if (GetClipBox(hdc, &limit) == ERROR) return FALSE;
-
- if (rect && !IntersectRect(&limit, &limit, rect)) return TRUE;
-
- if (macdrv_get_displays(&displays, &num_displays))
- return FALSE;
-
- for (i = 0; i < num_displays; i++)
- {
- RECT monrect = rect_from_cgrect(displays[i].frame);
- OffsetRect(&monrect, -origin.x, -origin.y);
- if (IntersectRect(&monrect, &monrect, &limit))
- {
- HMONITOR monitor = display_id_to_monitor(displays[i].displayID);
- TRACE("monitor %d handle %p @ %s\n", i, monitor, wine_dbgstr_rect(&monrect));
- if (!proc(monitor, hdc, &monrect, lparam))
- {
- ret = FALSE;
- break;
- }
- }
- }
- }
- else
- {
- if (macdrv_get_displays(&displays, &num_displays))
- return FALSE;
-
- for (i = 0; i < num_displays; i++)
- {
- RECT monrect = rect_from_cgrect(displays[i].frame);
- RECT unused;
- if (!rect || IntersectRect(&unused, &monrect, rect))
- {
- HMONITOR monitor = display_id_to_monitor(displays[i].displayID);
- TRACE("monitor %d handle %p @ %s\n", i, monitor, wine_dbgstr_rect(&monrect));
- if (!proc(monitor, 0, &monrect, lparam))
- {
- ret = FALSE;
- break;
- }
- }
- }
- }
-
- macdrv_free_displays(displays);
-
- return ret;
-}
-
-
/***********************************************************************
* EnumDisplaySettingsEx (MACDRV.@)
*
@@ -1323,58 +1245,6 @@ done:
return ret;
}
-
-/***********************************************************************
- * GetMonitorInfo (MACDRV.@)
- */
-BOOL CDECL macdrv_GetMonitorInfo(HMONITOR monitor, LPMONITORINFO info)
-{
- static const WCHAR adapter_name[] = { '\\','\\','.','\\','D','I','S','P','L','A','Y','1',0 };
- struct macdrv_display *displays;
- int num_displays;
- CGDirectDisplayID display_id;
- int i;
-
- TRACE("%p, %p\n", monitor, info);
-
- if (macdrv_get_displays(&displays, &num_displays))
- {
- ERR("couldn't get display list\n");
- SetLastError(ERROR_GEN_FAILURE);
- return FALSE;
- }
-
- display_id = monitor_to_display_id(monitor);
- for (i = 0; i < num_displays; i++)
- {
- if (displays[i].displayID == display_id)
- break;
- }
-
- if (i < num_displays)
- {
- info->rcMonitor = rect_from_cgrect(displays[i].frame);
- info->rcWork = rect_from_cgrect(displays[i].work_frame);
-
- info->dwFlags = (i == 0) ? MONITORINFOF_PRIMARY : 0;
-
- if (info->cbSize >= sizeof(MONITORINFOEXW))
- lstrcpyW(((MONITORINFOEXW*)info)->szDevice, adapter_name);
-
- TRACE(" -> rcMonitor %s rcWork %s dwFlags %08x\n", wine_dbgstr_rect(&info->rcMonitor),
- wine_dbgstr_rect(&info->rcWork), info->dwFlags);
- }
- else
- {
- ERR("invalid monitor handle\n");
- SetLastError(ERROR_INVALID_HANDLE);
- }
-
- macdrv_free_displays(displays);
- return (i < num_displays);
-}
-
-
/***********************************************************************
* SetDeviceGammaRamp (MACDRV.@)
*/
@@ -1640,6 +1510,7 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m
WCHAR nameW[MAX_PATH];
WCHAR bufferW[MAX_PATH];
HKEY hkey;
+ RECT rect;
BOOL ret = FALSE;
/* Create GUID_DEVCLASS_MONITOR instance */
@@ -1664,6 +1535,21 @@ static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *m
if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32,
(const BYTE *)&monitor->state_flags, sizeof(monitor->state_flags), 0))
goto done;
+ /* RcMonitor */
+ rect = rect_from_cgrect(monitor->rc_monitor);
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCMONITOR, DEVPROP_TYPE_BINARY,
+ (const BYTE *)&rect, sizeof(rect), 0))
+ goto done;
+ /* RcWork */
+ rect = rect_from_cgrect(monitor->rc_work);
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_RCWORK, DEVPROP_TYPE_BINARY,
+ (const BYTE *)&rect, sizeof(rect), 0))
+ goto done;
+ /* Adapter name */
+ sprintfW(bufferW, adapter_name_fmtW, video_index + 1);
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_ADAPTERNAME, DEVPROP_TYPE_STRING,
+ (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR), 0))
+ goto done;
ret = TRUE;
done:
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 96ebb97e76..676adb435b 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -293,6 +293,10 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
{
/* Name, in UTF-8 encoding */
char name[128];
+ /* as RcMonitor in MONITORINFO struct after conversion by rect_from_cgrect */
+ CGRect rc_monitor;
+ /* as RcWork in MONITORINFO struct after conversion by rect_from_cgrect */
+ CGRect rc_work;
/* StateFlags in DISPLAY_DEVICE struct */
uint32_t state_flags;
};
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index 6fa723a690..39cf33370b 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -12,14 +12,12 @@
@ cdecl CreateWindow(long) macdrv_CreateWindow
@ cdecl DestroyCursorIcon(long) macdrv_DestroyCursorIcon
@ cdecl DestroyWindow(long) macdrv_DestroyWindow
-@ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors
@ cdecl EnumDisplaySettingsEx(ptr long ptr long) macdrv_EnumDisplaySettingsEx
@ cdecl GetCursorPos(ptr) macdrv_GetCursorPos
@ cdecl GetKeyboardLayout(long) macdrv_GetKeyboardLayout
@ cdecl GetKeyboardLayoutList(long ptr) macdrv_GetKeyboardLayoutList
@ cdecl GetKeyboardLayoutName(ptr) macdrv_GetKeyboardLayoutName
@ cdecl GetKeyNameText(long ptr long) macdrv_GetKeyNameText
-@ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo
@ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx
@ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) macdrv_MsgWaitForMultipleObjectsEx
@ cdecl RegisterHotKey(long long long) macdrv_RegisterHotKey
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winemac.drv/display.c | 8 ++++++--
dlls/winemac.drv/macdrv.h | 2 +-
dlls/winemac.drv/macdrv_main.c | 2 +-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index a953e0c574..236f63d563 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -946,6 +946,8 @@ better:
SendMessageW(GetDesktopWindow(), WM_MACDRV_UPDATE_DESKTOP_RECT, mode_bpp,
MAKELPARAM(width, height));
ret = DISP_CHANGE_SUCCESSFUL;
+
+ macdrv_init_display_devices(TRUE);
}
else
{
@@ -1452,6 +1454,8 @@ void macdrv_displays_changed(const macdrv_event *event)
free_display_mode_descriptor(desc);
CGDisplayModeRelease(mode);
+ macdrv_init_display_devices(TRUE);
+
if (is_original && retina_enabled)
{
width *= 2;
@@ -1728,7 +1732,7 @@ static void cleanup_devices(void)
*
* Initialize display device registry data.
*/
-void macdrv_init_display_devices(void)
+void macdrv_init_display_devices(BOOL force)
{
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
HANDLE mutex;
@@ -1755,7 +1759,7 @@ void macdrv_init_display_devices(void)
}
/* Avoid unnecessary reinit */
- if (disposition != REG_CREATED_NEW_KEY)
+ if (!force && disposition != REG_CREATED_NEW_KEY)
goto done;
TRACE("\n");
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index b9f58b90da..a7c0b4cac8 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -223,7 +223,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP
extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN;
-extern void macdrv_init_display_devices(void) DECLSPEC_HIDDEN;
+extern void macdrv_init_display_devices(BOOL force) DECLSPEC_HIDDEN;
/**************************************************************************
* Mac IME driver
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 038578491f..694a46b11e 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -299,7 +299,7 @@ static BOOL process_attach(void)
return FALSE;
}
- macdrv_init_display_devices();
+ macdrv_init_display_devices(FALSE);
return TRUE;
}
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_display.m | 108 +++++++++++++++++++++++++++++++++++++++
dlls/winemac.drv/display.c | 103 +++++++++++++++++++++++++++++++++++--
dlls/winemac.drv/macdrv_cocoa.h | 14 +++++
dlls/winemac.drv/macdrv_main.c | 2 +
4 files changed, 222 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 92d233df89..f068a8aa3f 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -577,3 +577,111 @@ void macdrv_free_adapters(struct macdrv_adapter* adapters)
if (adapters)
free(adapters);
}
+
+/***********************************************************************
+ * macdrv_get_monitors
+ *
+ * Get a list of monitors under adapter_id. The first monitor is primary if adapter is primary.
+ * Call macdrv_free_monitors() when you are done using the data.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** new_monitors, int* count)
+{
+ struct macdrv_monitor* monitors = NULL;
+ struct macdrv_monitor* realloc_monitors;
+ struct macdrv_display* displays = NULL;
+ CGDirectDisplayID display_ids[16];
+ uint32_t display_id_count;
+ int primary_index = 0;
+ int monitor_count = 0;
+ int display_count;
+ int capacity;
+ int ret = -1;
+ int i, j;
+
+ /* 2 should be enough for most cases */
+ capacity = 2;
+ monitors = calloc(capacity, sizeof(*monitors));
+ if (!monitors)
+ return -1;
+
+ /* Report an inactive monitor */
+ if (!CGDisplayIsActive(adapter_id) && !CGDisplayIsInMirrorSet(adapter_id))
+ {
+ strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor");
+ monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED;
+ monitor_count++;
+ }
+ /* Report active and mirrored monitors in the same mirroring set */
+ else
+ {
+ if (CGGetOnlineDisplayList(sizeof(display_ids) / sizeof(display_ids[0]), display_ids, &display_id_count)
+ != kCGErrorSuccess)
+ goto done;
+
+ if (macdrv_get_displays(&displays, &display_count))
+ goto done;
+
+ for (i = 0; i < display_id_count; i++)
+ {
+ if (display_ids[i] != adapter_id && CGDisplayMirrorsDisplay(display_ids[i]) != adapter_id)
+ continue;
+
+ /* Find and fill in monitor info */
+ for (j = 0; j < display_count; j++)
+ {
+ if (displays[i].displayID == display_ids[j]
+ || CGDisplayMirrorsDisplay(display_ids[i]) == displays[j].displayID)
+ {
+ /* Allocate more space if needed */
+ if (monitor_count >= capacity)
+ {
+ capacity *= 2;
+ realloc_monitors = realloc(monitors, sizeof(*monitors) * capacity);
+ if (!realloc_monitors)
+ goto done;
+ monitors = realloc_monitors;
+ }
+
+ if (CGDisplayIsMain(display_ids[j]))
+ primary_index = monitor_count;
+
+ strcpy(monitors[monitor_count].name, "Generic Non-PnP Monitor");
+ monitors[monitor_count].state_flags = DISPLAY_DEVICE_ATTACHED | DISPLAY_DEVICE_ACTIVE;
+ monitor_count++;
+ }
+ }
+ }
+
+ /* Make sure the first monitor on primary adapter is primary */
+ if (primary_index)
+ {
+ struct macdrv_monitor tmp;
+ tmp = monitors[0];
+ monitors[0] = monitors[primary_index];
+ monitors[primary_index] = tmp;
+ }
+ }
+
+ *new_monitors = monitors;
+ *count = monitor_count;
+ ret = 0;
+done:
+ if (displays)
+ macdrv_free_displays(displays);
+ if (ret)
+ macdrv_free_monitors(monitors);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_free_monitors
+ *
+ * Frees an monitor list allocated from macdrv_get_monitors()
+ */
+void macdrv_free_monitors(struct macdrv_monitor* monitors)
+{
+ if (monitors)
+ free(monitors);
+}
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index 97ebca22e5..a953e0c574 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -51,15 +51,19 @@ struct display_mode_descriptor
BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW devmode, DWORD flags);
+/* Wine specific monitor properties */
+DEFINE_DEVPROPKEY(WINE_DEVPROPKEY_MONITOR_STATEFLAGS, 0x233a9ef3, 0xafc4, 0x4abd, 0xb5, 0x64, 0xc3, 0x2f, 0x21, 0xf1, 0x53, 0x5b, 2);
static const char initial_mode_key[] = "Initial Display Mode";
static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
+static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0};
static const WCHAR pciW[] = {'P','C','I',0};
static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
static const WCHAR symbolic_link_valueW[]= {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
static const WCHAR gpu_idW[] = {'G','P','U','I','D',0};
+static const WCHAR mointor_id_fmtW[] = {'M','o','n','i','t','o','r','I','D','%','d',0};
static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
static const WCHAR guid_fmtW[] = {
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
@@ -101,6 +105,13 @@ static const WCHAR nt_classW[] = {
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'C','o','n','t','r','o','l','\\',
'C','l','a','s','s','\\',0};
+static const WCHAR monitor_instance_fmtW[] = {
+ 'D','I','S','P','L','A','Y','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r','\\',
+ '%','0','4','X','&','%','0','4','X',0};
+static const WCHAR monitor_hardware_idW[] = {
+ 'M','O','N','I','T','O','R','\\',
+ 'D','e','f','a','u','l','t','_','M','o','n','i','t','o','r',0,0};
static CFArrayRef modes;
@@ -1544,7 +1555,7 @@ done:
*
* Return FALSE on failure and TRUE on success.
*/
-static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, int adapter_index,
+static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, int adapter_index, int monitor_count,
const struct macdrv_gpu *gpu, const WCHAR *guid_string, const WCHAR *gpu_driver,
const struct macdrv_adapter *adapter)
{
@@ -1554,6 +1565,7 @@ static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index,
HKEY hkey = NULL;
BOOL ret = FALSE;
LSTATUS ls;
+ INT i;
sprintfW(key_nameW, device_video_fmtW, video_index);
lstrcpyW(bufferW, machine_prefixW);
@@ -1588,6 +1600,15 @@ static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index,
if (RegSetValueExW(hkey, gpu_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
+ /* Write all monitor instances paths under this adapter */
+ for (i = 0; i < monitor_count; i++)
+ {
+ sprintfW(key_nameW, mointor_id_fmtW, i);
+ sprintfW(bufferW, monitor_instance_fmtW, video_index, i);
+ if (RegSetValueExW(hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto done;
+ }
+
/* Write StateFlags */
if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
sizeof(adapter->state_flags)))
@@ -1601,6 +1622,52 @@ done:
return ret;
}
+/***********************************************************************
+ * macdrv_init_monitor
+ *
+ * Initialize an monitor.
+ *
+ * Return FALSE on failure and TRUE on success.
+ */
+static BOOL macdrv_init_monitor(HDEVINFO devinfo, const struct macdrv_monitor *monitor, int monitor_index,
+ int video_index)
+{
+ SP_DEVINFO_DATA device_data = {sizeof(SP_DEVINFO_DATA)};
+ WCHAR nameW[MAX_PATH];
+ WCHAR bufferW[MAX_PATH];
+ HKEY hkey;
+ BOOL ret = FALSE;
+
+ /* Create GUID_DEVCLASS_MONITOR instance */
+ sprintfW(bufferW, monitor_instance_fmtW, video_index, monitor_index);
+ MultiByteToWideChar(CP_UTF8, 0, monitor->name, -1, nameW, ARRAY_SIZE(nameW));
+ SetupDiCreateDeviceInfoW(devinfo, bufferW, &GUID_DEVCLASS_MONITOR, nameW, NULL, 0, &device_data);
+ if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
+ goto done;
+
+ /* Write HardwareID registry property */
+ if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID,
+ (const BYTE *)monitor_hardware_idW, sizeof(monitor_hardware_idW)))
+ goto done;
+
+ /* Create driver key */
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+ RegCloseKey(hkey);
+
+ /* FIXME:
+ * Following properties are Wine specific, see comments in macdrv_init_adapter for details */
+ /* StateFlags */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &WINE_DEVPROPKEY_MONITOR_STATEFLAGS, DEVPROP_TYPE_UINT32,
+ (const BYTE *)&monitor->state_flags, sizeof(monitor->state_flags), 0))
+ goto done;
+
+ ret = TRUE;
+done:
+ if (!ret)
+ ERR("Failed to initialize monitor\n");
+ return ret;
+}
+
static void prepare_devices(HKEY video_hkey)
{
static const BOOL not_present = FALSE;
@@ -1608,6 +1675,15 @@ static void prepare_devices(HKEY video_hkey)
HDEVINFO devinfo;
DWORD i = 0;
+ /* Remove all monitors */
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_MONITOR, displayW, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ if (!SetupDiRemoveDevice(devinfo, &device_data))
+ ERR("Failed to remove monitor\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+
/* Clean up old adapter keys for reinitialization */
RegDeleteTreeW(video_hkey, NULL);
@@ -1616,6 +1692,7 @@ static void prepare_devices(HKEY video_hkey)
* case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
* of prefix copying or having devices unplugged. But then we couldn't simply delete GPUs because we need to retain
* the same GUID for the same GPU. */
+ i = 0;
devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
{
@@ -1657,9 +1734,10 @@ void macdrv_init_display_devices(void)
HANDLE mutex;
struct macdrv_gpu *gpus = NULL;
struct macdrv_adapter *adapters = NULL;
- INT gpu_count, adapter_count;
- INT gpu, adapter;
- HDEVINFO gpu_devinfo = NULL;
+ struct macdrv_monitor *monitors = NULL;
+ INT gpu_count, adapter_count, monitor_count;
+ INT gpu, adapter, monitor;
+ HDEVINFO gpu_devinfo = NULL, monitor_devinfo = NULL;
HKEY video_hkey = NULL;
INT video_index = 0;
DWORD disposition = 0;
@@ -1685,6 +1763,7 @@ void macdrv_init_display_devices(void)
prepare_devices(video_hkey);
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
+ monitor_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_MONITOR, NULL);
/* Initialize GPUs */
if (macdrv_get_gpus(&gpus, &gpu_count))
@@ -1701,10 +1780,22 @@ void macdrv_init_display_devices(void)
for (adapter = 0; adapter < adapter_count; adapter++)
{
- if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, &gpus[gpu], guidW, driverW,
+ if (macdrv_get_monitors(adapters[adapter].id, &monitors, &monitor_count))
+ goto done;
+
+ if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, monitor_count, &gpus[gpu], guidW, driverW,
&adapters[adapter]))
goto done;
+ /* Initialize monitors */
+ for (monitor = 0; monitor < monitor_count; monitor++)
+ {
+ if (!macdrv_init_monitor(monitor_devinfo, &monitors[monitor], monitor, video_index))
+ goto done;
+ }
+
+ macdrv_free_monitors(monitors);
+ monitors = NULL;
video_index++;
}
@@ -1714,6 +1805,7 @@ void macdrv_init_display_devices(void)
done:
cleanup_devices();
+ SetupDiDestroyDeviceInfoList(monitor_devinfo);
SetupDiDestroyDeviceInfoList(gpu_devinfo);
RegCloseKey(video_hkey);
@@ -1722,4 +1814,5 @@ done:
macdrv_free_gpus(gpus);
macdrv_free_adapters(adapters);
+ macdrv_free_monitors(monitors);
}
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index b960e902e3..96ebb97e76 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -261,6 +261,9 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
/* Used DISPLAY_DEVICE.StateFlags for adapters */
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
+/* Used DISPLAY_DEVICE.StateFlags for monitors */
+#define DISPLAY_DEVICE_ACTIVE 0x00000001
+#define DISPLAY_DEVICE_ATTACHED 0x00000002
/* Represent a physical GPU in the PCI slots */
struct macdrv_gpu
@@ -285,6 +288,15 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
uint32_t state_flags;
};
+/* Represent a monitor in EnumDisplayDevices context */
+struct macdrv_monitor
+{
+ /* Name, in UTF-8 encoding */
+ char name[128];
+ /* StateFlags in DISPLAY_DEVICE struct */
+ uint32_t state_flags;
+};
+
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
extern int macdrv_set_display_mode(const struct macdrv_display* display,
@@ -293,6 +305,8 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
extern void macdrv_free_gpus(struct macdrv_gpu* gpus) DECLSPEC_HIDDEN;
extern int macdrv_get_adapters(uint64_t gpu_id, struct macdrv_adapter** adapters, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_adapters(struct macdrv_adapter* adapters) DECLSPEC_HIDDEN;
+extern int macdrv_get_monitors(uint32_t adapter_id, struct macdrv_monitor** monitors, int* count) DECLSPEC_HIDDEN;
+extern void macdrv_free_monitors(struct macdrv_monitor* monitors) DECLSPEC_HIDDEN;
/* event */
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c
index 544d448f9f..038578491f 100644
--- a/dlls/winemac.drv/macdrv_main.c
+++ b/dlls/winemac.drv/macdrv_main.c
@@ -299,6 +299,8 @@ static BOOL process_attach(void)
return FALSE;
}
+ macdrv_init_display_devices();
+
return TRUE;
}
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_display.m | 99 +++++++++++++++++++++++++++++
dlls/winemac.drv/display.c | 134 +++++++++++++++++++++++++++++++++++++--
dlls/winemac.drv/macdrv_cocoa.h | 15 +++++
3 files changed, 241 insertions(+), 7 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 1fa269e20c..92d233df89 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -26,6 +26,8 @@
#endif
#include "macdrv_cocoa.h"
+static uint64_t dedicated_gpu_id;
+static uint64_t integrated_gpu_id;
/***********************************************************************
* convert_display_rect
@@ -293,6 +295,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
/* Hide the integrated GPU if the system default device is a dedicated GPU */
if (!primary_device.isLowPower)
{
+ dedicated_gpu_id = primary_gpu.id;
hide_integrated = TRUE;
}
@@ -303,6 +306,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
if (hide_integrated && devices[i].isLowPower)
{
+ integrated_gpu_id = gpus[gpu_count].id;
continue;
}
@@ -408,6 +412,7 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
* Assuming integrated GPU vendor is Intel for now */
if (gpus[i].vendor_id == 0x8086)
{
+ integrated_gpu_id = gpus[i].id;
integrated_index = i;
}
@@ -430,6 +435,7 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
else if (primary_index == gpu_count - 1)
primary_index = integrated_index;
+ dedicated_gpu_id = gpus[primary_index].id;
gpu_count--;
}
}
@@ -462,6 +468,9 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
*/
int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count)
{
+ integrated_gpu_id = 0;
+ dedicated_gpu_id = 0;
+
if (!macdrv_get_gpus_from_metal(new_gpus, count))
return 0;
else
@@ -478,3 +487,93 @@ void macdrv_free_gpus(struct macdrv_gpu* gpus)
if (gpus)
free(gpus);
}
+
+/***********************************************************************
+ * macdrv_get_adapters
+ *
+ * Get a list of adapters under gpu_id. The first adapter is primary if GPU is primary.
+ * Call macdrv_free_adapters() when you are done using the data.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+int macdrv_get_adapters(uint64_t gpu_id, struct macdrv_adapter** new_adapters, int* count)
+{
+ CGDirectDisplayID display_ids[16];
+ uint32_t display_id_count;
+ struct macdrv_adapter* adapters;
+ struct macdrv_gpu gpu;
+ int primary_index = 0;
+ int adapter_count = 0;
+ int ret = -1;
+ uint32_t i;
+
+ if (CGGetOnlineDisplayList(sizeof(display_ids) / sizeof(display_ids[0]), display_ids, &display_id_count)
+ != kCGErrorSuccess)
+ return -1;
+
+ if (!display_id_count)
+ {
+ *new_adapters = NULL;
+ *count = 0;
+ return 0;
+ }
+
+ /* Actual adapter count may be less */
+ adapters = calloc(display_id_count, sizeof(*adapters));
+ if (!adapters)
+ return -1;
+
+ for (i = 0; i < display_id_count; i++)
+ {
+ /* Mirrored displays are under the same adapter with primary display, so they doesn't increase adapter count */
+ if (CGDisplayMirrorsDisplay(display_ids[i]) != kCGNullDirectDisplay)
+ continue;
+
+ if (macdrv_get_gpu_info_from_display_id(&gpu, display_ids[i]))
+ goto done;
+
+ if (gpu.id == gpu_id || (gpu_id == dedicated_gpu_id && gpu.id == integrated_gpu_id))
+ {
+ adapters[adapter_count].id = display_ids[i];
+
+ if (CGDisplayIsMain(display_ids[i]))
+ {
+ adapters[adapter_count].state_flags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
+ primary_index = adapter_count;
+ }
+
+ if (CGDisplayIsActive(display_ids[i]))
+ adapters[adapter_count].state_flags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+
+ adapter_count++;
+ }
+ }
+
+ /* Make sure the first adapter is primary if the GPU is primary */
+ if (primary_index)
+ {
+ struct macdrv_adapter tmp;
+ tmp = adapters[0];
+ adapters[0] = adapters[primary_index];
+ adapters[primary_index] = tmp;
+ }
+
+ *new_adapters = adapters;
+ *count = adapter_count;
+ ret = 0;
+done:
+ if (ret)
+ macdrv_free_adapters(adapters);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_free_adapters
+ *
+ * Frees an adapter list allocated from macdrv_get_adapters()
+ */
+void macdrv_free_adapters(struct macdrv_adapter* adapters)
+{
+ if (adapters)
+ free(adapters);
+}
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index 88f8f8f4f3..97ebca22e5 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -58,6 +58,9 @@ static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e
static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
static const WCHAR pciW[] = {'P','C','I',0};
static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
+static const WCHAR symbolic_link_valueW[]= {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0};
+static const WCHAR gpu_idW[] = {'G','P','U','I','D',0};
+static const WCHAR state_flagsW[] = {'S','t','a','t','e','F','l','a','g','s',0};
static const WCHAR guid_fmtW[] = {
'{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
'%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
@@ -78,6 +81,26 @@ static const WCHAR video_keyW[] = {
'H','A','R','D','W','A','R','E','\\',
'D','E','V','I','C','E','M','A','P','\\',
'V','I','D','E','O',0};
+static const WCHAR adapter_key_fmtW[] = {
+ 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'V','i','d','e','o','\\',
+ '%','s','\\',
+ '%','0','4','x',0};
+static const WCHAR device_video_fmtW[] = {
+ '\\','D','e','v','i','c','e','\\',
+ 'V','i','d','e','o','%','d',0};
+static const WCHAR machine_prefixW[] = {
+ '\\','R','e','g','i','s','t','r','y','\\',
+ 'M','a','c','h','i','n','e','\\',0};
+static const WCHAR nt_classW[] = {
+ '\\','R','e','g','i','s','t','r','y','\\',
+ 'M','a','c','h','i','n','e','\\',
+ 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'C','o','n','t','r','o','l','\\',
+ 'C','l','a','s','s','\\',0};
static CFArrayRef modes;
@@ -1432,11 +1455,12 @@ void macdrv_displays_changed(const macdrv_event *event)
/***********************************************************************
* macdrv_init_gpu
*
- * Initialize a GPU instance.
+ * Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter.
*
* Return FALSE on failure and TRUE on success.
*/
-static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index)
+static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index, WCHAR *guid_string,
+ WCHAR *driver)
{
static const BOOL present = TRUE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
@@ -1484,6 +1508,13 @@ static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int
goto done;
RegCloseKey(hkey);
+ /* Retrieve driver value for adapters */
+ if (!SetupDiGetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_DRIVER, NULL, (BYTE *)bufferW, sizeof(bufferW),
+ NULL))
+ goto done;
+ lstrcpyW(driver, nt_classW);
+ lstrcatW(driver, bufferW);
+
/* Write GUID in VideoID in .../instance/Device Parameters, reuse the GUID if it's existent */
hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL);
@@ -1496,6 +1527,7 @@ static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int
if (RegSetValueExW(hkey, video_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
goto done;
}
+ lstrcpyW(guid_string, bufferW);
ret = TRUE;
done:
@@ -1505,13 +1537,80 @@ done:
return ret;
}
-static void prepare_devices(void)
+/***********************************************************************
+ * macdrv_init_adapter
+ *
+ * Initialize an adapter.
+ *
+ * Return FALSE on failure and TRUE on success.
+ */
+static BOOL macdrv_init_adapter(HKEY video_hkey, int video_index, int gpu_index, int adapter_index,
+ const struct macdrv_gpu *gpu, const WCHAR *guid_string, const WCHAR *gpu_driver,
+ const struct macdrv_adapter *adapter)
+{
+ WCHAR adapter_keyW[MAX_PATH];
+ WCHAR key_nameW[MAX_PATH];
+ WCHAR bufferW[1024];
+ HKEY hkey = NULL;
+ BOOL ret = FALSE;
+ LSTATUS ls;
+
+ sprintfW(key_nameW, device_video_fmtW, video_index);
+ lstrcpyW(bufferW, machine_prefixW);
+ sprintfW(adapter_keyW, adapter_key_fmtW, guid_string, adapter_index);
+ lstrcatW(bufferW, adapter_keyW);
+
+ /* Write value of \Device\Video? (adapter key) in HKLM\HARDWARE\DEVICEMAP\VIDEO\ */
+ if (RegSetValueExW(video_hkey, key_nameW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto done;
+
+ /* Create HKLM\System\CurrentControlSet\Control\Video\{GPU GUID}\{Adapter Index} link to GPU driver */
+ ls = RegCreateKeyExW(HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+ KEY_ALL_ACCESS, NULL, &hkey, NULL);
+ if (ls == ERROR_ALREADY_EXISTS)
+ RegCreateKeyExW(HKEY_LOCAL_MACHINE, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE | REG_OPTION_OPEN_LINK,
+ KEY_ALL_ACCESS, NULL, &hkey, NULL);
+ if (RegSetValueExW(hkey, symbolic_link_valueW, 0, REG_LINK, (const BYTE *)gpu_driver,
+ lstrlenW(gpu_driver) * sizeof(WCHAR)))
+ goto done;
+ RegCloseKey(hkey);
+ hkey = NULL;
+
+ /* FIXME:
+ * Following information is Wine specific, it doesn't really exist on Windows. It is used so that we can
+ * implement EnumDisplayDevices etc by querying registry only. This information is most likely reported by the
+ * device driver on Windows */
+ RegCreateKeyExW(HKEY_CURRENT_CONFIG, adapter_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_WRITE, NULL, &hkey, NULL);
+
+ /* Write GPU instance path so that we can find the GPU instance via adapters quickly. Another way is trying to match
+ * them via the GUID in Device Paramters/VideoID, but it would required enumrating all GPU instances */
+ sprintfW(bufferW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index);
+ if (RegSetValueExW(hkey, gpu_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto done;
+
+ /* Write StateFlags */
+ if (RegSetValueExW(hkey, state_flagsW, 0, REG_DWORD, (const BYTE *)&adapter->state_flags,
+ sizeof(adapter->state_flags)))
+ goto done;
+
+ ret = TRUE;
+done:
+ RegCloseKey(hkey);
+ if (!ret)
+ ERR("Failed to initialize adapter\n");
+ return ret;
+}
+
+static void prepare_devices(HKEY video_hkey)
{
static const BOOL not_present = FALSE;
SP_DEVINFO_DATA device_data = {sizeof(device_data)};
HDEVINFO devinfo;
DWORD i = 0;
+ /* Clean up old adapter keys for reinitialization */
+ RegDeleteTreeW(video_hkey, NULL);
+
/* FIXME:
* Currently SetupDiGetClassDevsW with DIGCF_PRESENT is unsupported, So we need to clean up not present devices in
* case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
@@ -1557,11 +1656,15 @@ void macdrv_init_display_devices(void)
static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
HANDLE mutex;
struct macdrv_gpu *gpus = NULL;
- INT gpu_count;
- INT gpu;
+ struct macdrv_adapter *adapters = NULL;
+ INT gpu_count, adapter_count;
+ INT gpu, adapter;
HDEVINFO gpu_devinfo = NULL;
HKEY video_hkey = NULL;
+ INT video_index = 0;
DWORD disposition = 0;
+ WCHAR guidW[40];
+ WCHAR driverW[1024];
mutex = CreateMutexW(NULL, FALSE, init_mutexW);
WaitForSingleObject(mutex, INFINITE);
@@ -1579,7 +1682,7 @@ void macdrv_init_display_devices(void)
TRACE("\n");
- prepare_devices();
+ prepare_devices(video_hkey);
gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
@@ -1589,8 +1692,24 @@ void macdrv_init_display_devices(void)
for (gpu = 0; gpu < gpu_count; gpu++)
{
- if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu))
+ if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu, guidW, driverW))
goto done;
+
+ /* Initialize adapters */
+ if (macdrv_get_adapters(gpus[gpu].id, &adapters, &adapter_count))
+ goto done;
+
+ for (adapter = 0; adapter < adapter_count; adapter++)
+ {
+ if (!macdrv_init_adapter(video_hkey, video_index, gpu, adapter, &gpus[gpu], guidW, driverW,
+ &adapters[adapter]))
+ goto done;
+
+ video_index++;
+ }
+
+ macdrv_free_adapters(adapters);
+ adapters = NULL;
}
done:
@@ -1602,4 +1721,5 @@ done:
CloseHandle(mutex);
macdrv_free_gpus(gpus);
+ macdrv_free_adapters(adapters);
}
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 513746fa0e..b960e902e3 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -258,6 +258,10 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
/* display */
+/* Used DISPLAY_DEVICE.StateFlags for adapters */
+#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
+#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
+
/* Represent a physical GPU in the PCI slots */
struct macdrv_gpu
{
@@ -272,12 +276,23 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
uint32_t revision_id;
};
+/* Represent an adapter in EnumDisplayDevices context */
+struct macdrv_adapter
+{
+ /* ID to uniquely identify an adapter. Currently it's a CGDirectDisplayID */
+ uint32_t id;
+ /* as StateFlags in DISPLAY_DEVICE struct */
+ uint32_t state_flags;
+};
+
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
extern int macdrv_set_display_mode(const struct macdrv_display* display,
CGDisplayModeRef display_mode) DECLSPEC_HIDDEN;
extern int macdrv_get_gpus(struct macdrv_gpu** gpus, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_gpus(struct macdrv_gpu* gpus) DECLSPEC_HIDDEN;
+extern int macdrv_get_adapters(uint64_t gpu_id, struct macdrv_adapter** adapters, int* count) DECLSPEC_HIDDEN;
+extern void macdrv_free_adapters(struct macdrv_adapter* adapters) DECLSPEC_HIDDEN;
/* event */
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
dlls/winemac.drv/cocoa_display.m | 115 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 114 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 336398c11c..1fa269e20c 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -18,7 +18,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include "config.h"
+
#import <AppKit/AppKit.h>
+#ifdef HAVE_METAL_METAL_H
+#import <Metal/Metal.h>
+#endif
#include "macdrv_cocoa.h"
@@ -231,6 +236,111 @@ static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_en
return ret;
}
+#ifdef HAVE_METAL_METAL_H
+
+/***********************************************************************
+ * macdrv_get_gpu_info_from_registry_id
+ *
+ * Get GPU information from a Metal device registry id.
+ *
+ * Returns non-zero value on failure.
+ */
+static int macdrv_get_gpu_info_from_registry_id(struct macdrv_gpu* gpu, uint64_t registry_id)
+{
+ int ret;
+ io_registry_entry_t entry;
+
+ entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(registry_id));
+ ret = macdrv_get_gpu_info_from_entry(gpu, entry);
+ IOObjectRelease(entry);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpus_from_metal
+ *
+ * Get a list of GPUs from Metal.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
+{
+ struct macdrv_gpu* gpus = NULL;
+ struct macdrv_gpu primary_gpu;
+ id<MTLDevice> primary_device;
+ BOOL hide_integrated = FALSE;
+ int primary_index = 0, i;
+ int gpu_count = 0;
+ int ret = -1;
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray<id<MTLDevice>>* devices = [MTLCopyAllDevices() autorelease];
+ /* Test if Metal is available */
+ if (!devices.count || ![devices[0] respondsToSelector:@selector(registryID)])
+ goto done;
+
+ gpus = calloc(devices.count, sizeof(*gpus));
+ if (!gpus)
+ goto done;
+
+ /* Use MTLCreateSystemDefaultDevice instead of CGDirectDisplayCopyCurrentMetalDevice(CGMainDisplayID()) to get
+ * the primary GPU because we need to hide the integrated GPU for an automatic graphic switching pair to avoid apps
+ * using the integrated GPU. This is the behavior of Windows on a Mac. */
+ primary_device = [MTLCreateSystemDefaultDevice() autorelease];
+ if (macdrv_get_gpu_info_from_registry_id(&primary_gpu, primary_device.registryID))
+ goto done;
+
+ /* Hide the integrated GPU if the system default device is a dedicated GPU */
+ if (!primary_device.isLowPower)
+ {
+ hide_integrated = TRUE;
+ }
+
+ for (i = 0; i < devices.count; i++)
+ {
+ if (macdrv_get_gpu_info_from_registry_id(&gpus[gpu_count], devices[i].registryID))
+ goto done;
+
+ if (hide_integrated && devices[i].isLowPower)
+ {
+ continue;
+ }
+
+ if (gpus[gpu_count].id == primary_gpu.id)
+ primary_index = gpu_count;
+
+ gpu_count++;
+ }
+
+ /* Make sure the first GPU is primary */
+ if (primary_index)
+ {
+ struct macdrv_gpu tmp;
+ tmp = gpus[0];
+ gpus[0] = gpus[primary_index];
+ gpus[primary_index] = tmp;
+ }
+
+ *new_gpus = gpus;
+ *count = gpu_count;
+ ret = 0;
+done:
+ if (ret)
+ macdrv_free_gpus(gpus);
+ [pool release];
+ return ret;
+}
+
+#else
+
+static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count)
+{
+ TRACE("Metal support not compiled in\n");
+ return -1;
+}
+
+#endif
+
/***********************************************************************
* macdrv_get_gpu_info_from_display_id
*
@@ -352,7 +462,10 @@ static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
*/
int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count)
{
- return macdrv_get_gpus_from_iokit(new_gpus, count);
+ if (!macdrv_get_gpus_from_metal(new_gpus, count))
+ return 0;
+ else
+ return macdrv_get_gpus_from_iokit(new_gpus, count);
}
/***********************************************************************
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
---
v2: Supersede 167500~167504.
Split GPU initialization patch.
Add DriverDateData registry property to display adapters.
dlls/winemac.drv/Makefile.in | 2 +-
dlls/winemac.drv/cocoa_display.m | 262 +++++++++++++++++++++++++++++++++++++++
dlls/winemac.drv/display.c | 206 ++++++++++++++++++++++++++++++
dlls/winemac.drv/macdrv.h | 1 +
dlls/winemac.drv/macdrv_cocoa.h | 17 +++
5 files changed, 487 insertions(+), 1 deletion(-)
diff --git a/dlls/winemac.drv/Makefile.in b/dlls/winemac.drv/Makefile.in
index 3ffb7d666c..c6ae9733bd 100644
--- a/dlls/winemac.drv/Makefile.in
+++ b/dlls/winemac.drv/Makefile.in
@@ -1,5 +1,5 @@
MODULE = winemac.drv
-IMPORTS = uuid user32 gdi32 advapi32
+IMPORTS = uuid setupapi rpcrt4 user32 gdi32 advapi32
DELAYIMPORTS = ole32 shell32 imm32
EXTRALIBS = -framework AppKit -framework Carbon -framework Security -framework OpenGL -framework IOKit -framework CoreVideo $(METAL_LIBS)
diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m
index 93a0fbca35..336398c11c 100644
--- a/dlls/winemac.drv/cocoa_display.m
+++ b/dlls/winemac.drv/cocoa_display.m
@@ -103,3 +103,265 @@ void macdrv_free_displays(struct macdrv_display* displays)
{
free(displays);
}
+
+/***********************************************************************
+ * get_entry_property_uint32
+ *
+ * Get an io registry entry property of type uint32 and store it in value parameter.
+ *
+ * Returns non-zero value on failure.
+ */
+static int get_entry_property_uint32(io_registry_entry_t entry, CFStringRef property_name, uint32_t* value)
+{
+ CFDataRef data = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0);
+ if (!data)
+ return -1;
+
+ if (CFGetTypeID(data) != CFDataGetTypeID() || CFDataGetLength(data) != sizeof(uint32_t))
+ {
+ CFRelease(data);
+ return -1;
+ }
+
+ CFDataGetBytes(data, CFRangeMake(0, sizeof(uint32_t)), (UInt8*)value);
+ CFRelease(data);
+ return 0;
+}
+
+/***********************************************************************
+ * get_entry_property_string
+ *
+ * Get an io registry entry property of type string and write it in buffer parameter.
+ *
+ * Returns non-zero value on failure.
+ */
+static int get_entry_property_string(io_registry_entry_t entry, CFStringRef property_name, char* buffer,
+ size_t buffer_size)
+{
+ CFTypeRef type_ref;
+ CFDataRef data_ref;
+ CFStringRef string_ref;
+ size_t length;
+ int ret = -1;
+
+ type_ref = IORegistryEntrySearchCFProperty(entry, kIOServicePlane, property_name, kCFAllocatorDefault, 0);
+ if (!type_ref)
+ goto done;
+
+ if (CFGetTypeID(type_ref) == CFDataGetTypeID())
+ {
+ data_ref = type_ref;
+ length = CFDataGetLength(data_ref);
+ if (length + 1 > buffer_size)
+ goto done;
+ CFDataGetBytes(data_ref, CFRangeMake(0, length), (UInt8*)buffer);
+ buffer[length] = 0;
+ }
+ else if (CFGetTypeID(type_ref) == CFStringGetTypeID())
+ {
+ string_ref = type_ref;
+ if (!CFStringGetCString(string_ref, buffer, buffer_size, kCFStringEncodingUTF8))
+ goto done;
+ }
+ else
+ {
+ goto done;
+ }
+
+ ret = 0;
+done:
+ if (type_ref)
+ CFRelease(type_ref);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpu_info_from_entry
+ *
+ * Starting from entry, search upwards to find the PCI GPU. And get GPU information from the PCI GPU entry.
+ *
+ * Returns non-zero value on failure.
+ */
+static int macdrv_get_gpu_info_from_entry(struct macdrv_gpu* gpu, io_registry_entry_t entry)
+{
+ io_registry_entry_t parent_entry;
+ io_registry_entry_t gpu_entry;
+ kern_return_t result;
+ int ret = -1;
+ char buffer[64];
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ gpu_entry = entry;
+ while (![@"IOPCIDevice" isEqualToString:[(__bridge NSString*)IOObjectCopyClass(gpu_entry) autorelease]]
+ || get_entry_property_string(gpu_entry, CFSTR("IOName"), buffer, sizeof(buffer))
+ || strcmp(buffer, "display"))
+ {
+ result = IORegistryEntryGetParentEntry(gpu_entry, kIOServicePlane, &parent_entry);
+ if (gpu_entry != entry)
+ IOObjectRelease(gpu_entry);
+ if (result == kIOReturnSuccess)
+ {
+ gpu_entry = parent_entry;
+ }
+ else
+ {
+ [pool release];
+ return ret;
+ }
+ }
+
+ if (IORegistryEntryGetRegistryEntryID(gpu_entry, &gpu->id) != kIOReturnSuccess)
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("vendor-id"), &gpu->vendor_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("device-id"), &gpu->device_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("subsystem-id"), &gpu->subsys_id))
+ goto done;
+ if (get_entry_property_uint32(gpu_entry, CFSTR("revision-id"), &gpu->revision_id))
+ goto done;
+ if (get_entry_property_string(gpu_entry, CFSTR("model"), gpu->name, sizeof(gpu->name)))
+ goto done;
+
+ ret = 0;
+done:
+ if (gpu_entry != entry)
+ IOObjectRelease(gpu_entry);
+ [pool release];
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpu_info_from_display_id
+ *
+ * Get GPU information from a display id.
+ * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable.
+ *
+ * Returns non-zero value on failure.
+ */
+static int macdrv_get_gpu_info_from_display_id(struct macdrv_gpu* gpu, CGDirectDisplayID display_id)
+{
+ io_registry_entry_t entry = CGDisplayIOServicePort(display_id);
+ return macdrv_get_gpu_info_from_entry(gpu, entry);
+}
+
+/***********************************************************************
+ * macdrv_get_gpus_from_iokit
+ *
+ * Get a list of GPUs from IOKit.
+ * This is a fallback for 32bit build or older Mac OS version where Metal is unavailable.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+static int macdrv_get_gpus_from_iokit(struct macdrv_gpu** new_gpus, int* count)
+{
+ static const int MAX_GPUS = 4;
+ struct macdrv_gpu primary_gpu = {0};
+ io_registry_entry_t entry;
+ io_iterator_t iterator;
+ struct macdrv_gpu* gpus;
+ int integrated_index = -1;
+ int primary_index = 0;
+ int gpu_count = 0;
+ int ret = -1;
+ int i;
+
+ gpus = calloc(MAX_GPUS, sizeof(*gpus));
+ if (!gpus)
+ goto done;
+
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOPCIDevice"), &iterator)
+ != kIOReturnSuccess)
+ goto done;
+
+ while ((entry = IOIteratorNext(iterator)))
+ {
+ if (!macdrv_get_gpu_info_from_entry(&gpus[gpu_count], entry))
+ {
+ gpu_count++;
+ assert(gpu_count < MAX_GPUS);
+ }
+ IOObjectRelease(entry);
+ }
+ IOObjectRelease(iterator);
+
+ macdrv_get_gpu_info_from_display_id(&primary_gpu, CGMainDisplayID());
+
+ /* If there are more than two GPUs and an Intel card exists,
+ * assume an automatic graphics pair exists and hide the integrated GPU */
+ if (gpu_count > 1)
+ {
+ for (i = 0; i < gpu_count; i++)
+ {
+ /* FIXME:
+ * Find integrated GPU without Metal support.
+ * Assuming integrated GPU vendor is Intel for now */
+ if (gpus[i].vendor_id == 0x8086)
+ {
+ integrated_index = i;
+ }
+
+ if (gpus[i].id == primary_gpu.id)
+ {
+ primary_index = i;
+ }
+ }
+
+ if (integrated_index != -1)
+ {
+ if (integrated_index != gpu_count - 1)
+ gpus[integrated_index] = gpus[gpu_count - 1];
+
+ /* FIXME:
+ * Find the dedicated GPU in an automatic graphics switching pair and use that as primary GPU.
+ * Choose the first dedicated GPU as primary */
+ if (primary_index == integrated_index)
+ primary_index = 0;
+ else if (primary_index == gpu_count - 1)
+ primary_index = integrated_index;
+
+ gpu_count--;
+ }
+ }
+
+ /* Make sure the first GPU is primary */
+ if (primary_index)
+ {
+ struct macdrv_gpu tmp;
+ tmp = gpus[0];
+ gpus[0] = gpus[primary_index];
+ gpus[primary_index] = tmp;
+ }
+
+ *new_gpus = gpus;
+ *count = gpu_count;
+ ret = 0;
+done:
+ if (ret)
+ macdrv_free_gpus(gpus);
+ return ret;
+}
+
+/***********************************************************************
+ * macdrv_get_gpus
+ *
+ * Get a list of GPUs currently in the system. The first GPU is primary.
+ * Call macdrv_free_gpus() when you are done using the data.
+ *
+ * Returns non-zero value on failure with parameters unchanged and zero on success.
+ */
+int macdrv_get_gpus(struct macdrv_gpu** new_gpus, int* count)
+{
+ return macdrv_get_gpus_from_iokit(new_gpus, count);
+}
+
+/***********************************************************************
+ * macdrv_free_gpus
+ *
+ * Frees a GPU list allocated from macdrv_get_gpus()
+ */
+void macdrv_free_gpus(struct macdrv_gpu* gpus)
+{
+ if (gpus)
+ free(gpus);
+}
diff --git a/dlls/winemac.drv/display.c b/dlls/winemac.drv/display.c
index ed7766d1d4..88f8f8f4f3 100644
--- a/dlls/winemac.drv/display.c
+++ b/dlls/winemac.drv/display.c
@@ -25,6 +25,13 @@
#include "winuser.h"
#include "winreg.h"
#include "ddrawi.h"
+#include "rpc.h"
+#include "initguid.h"
+#include "devguid.h"
+#include "devpkey.h"
+#include "setupapi.h"
+#define WIN32_NO_STATUS
+#include "winternl.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(display);
@@ -47,6 +54,30 @@ BOOL CDECL macdrv_EnumDisplaySettingsEx(LPCWSTR devname, DWORD mode, LPDEVMODEW
static const char initial_mode_key[] = "Initial Display Mode";
static const WCHAR pixelencodingW[] = {'P','i','x','e','l','E','n','c','o','d','i','n','g',0};
+static const WCHAR driver_date_dataW[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
+static const WCHAR driver_descW[] = {'D','r','i','v','e','r','D','e','s','c',0};
+static const WCHAR pciW[] = {'P','C','I',0};
+static const WCHAR video_idW[] = {'V','i','d','e','o','I','D',0};
+static const WCHAR guid_fmtW[] = {
+ '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-','%','0','2','x','%','0','2','x','-',
+ '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
+static const WCHAR gpu_instance_fmtW[] = {
+ 'P','C','I','\\',
+ 'V','E','N','_','%','0','4','X','&',
+ 'D','E','V','_','%','0','4','X','&',
+ 'S','U','B','S','Y','S','_','%','0','8','X','&',
+ 'R','E','V','_','%','0','2','X','\\',
+ '%','0','8','X',0};
+static const WCHAR gpu_hardware_id_fmtW[] = {
+ 'P','C','I','\\',
+ 'V','E','N','_','%','0','4','X','&',
+ 'D','E','V','_','%','0','4','X','&',
+ 'S','U','B','S','Y','S','_','0','0','0','0','0','0','0','0','&',
+ 'R','E','V','_','0','0',0};
+static const WCHAR video_keyW[] = {
+ 'H','A','R','D','W','A','R','E','\\',
+ 'D','E','V','I','C','E','M','A','P','\\',
+ 'V','I','D','E','O',0};
static CFArrayRef modes;
@@ -1397,3 +1428,178 @@ void macdrv_displays_changed(const macdrv_event *event)
MAKELPARAM(width, height));
}
}
+
+/***********************************************************************
+ * macdrv_init_gpu
+ *
+ * Initialize a GPU instance.
+ *
+ * Return FALSE on failure and TRUE on success.
+ */
+static BOOL macdrv_init_gpu(HDEVINFO devinfo, const struct macdrv_gpu *gpu, int gpu_index)
+{
+ static const BOOL present = TRUE;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ WCHAR instanceW[MAX_PATH];
+ WCHAR nameW[MAX_PATH];
+ WCHAR bufferW[1024];
+ FILETIME filetime;
+ HKEY hkey = NULL;
+ GUID guid;
+ INT written;
+ DWORD size;
+ BOOL ret = FALSE;
+
+ sprintfW(instanceW, gpu_instance_fmtW, gpu->vendor_id, gpu->device_id, gpu->subsys_id, gpu->revision_id, gpu_index);
+ MultiByteToWideChar(CP_UTF8, 0, gpu->name, -1, nameW, ARRAY_SIZE(nameW));
+ if (!SetupDiOpenDeviceInfoW(devinfo, instanceW, NULL, 0, &device_data))
+ {
+ SetupDiCreateDeviceInfoW(devinfo, instanceW, &GUID_DEVCLASS_DISPLAY, nameW, NULL, 0, &device_data);
+ if (!SetupDiRegisterDeviceInfo(devinfo, &device_data, 0, NULL, NULL, NULL))
+ goto done;
+ }
+
+ /* Write HardwareID registry property, REG_MULTI_SZ */
+ written = sprintfW(bufferW, gpu_hardware_id_fmtW, gpu->vendor_id, gpu->device_id);
+ bufferW[written + 1] = 0;
+ if (!SetupDiSetDeviceRegistryPropertyW(devinfo, &device_data, SPDRP_HARDWAREID, (const BYTE *)bufferW,
+ (written + 2) * sizeof(WCHAR)))
+ goto done;
+
+ /* Write DEVPKEY_Device_IsPresent property */
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
+ (const BYTE *)&present, sizeof(present), 0))
+ goto done;
+
+ /* Open driver key.
+ * This is where HKLM\System\CurrentControlSet\Control\Video\{GPU GUID}\{Adapter Index} links to */
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+
+ /* Write DriverDesc value */
+ if (RegSetValueExW(hkey, driver_descW, 0, REG_SZ, (const BYTE *)nameW, (lstrlenW(nameW) + 1) * sizeof(WCHAR)))
+ goto done;
+ /* Write DriverDateData value, using current time as driver date, needed by Evoland */
+ GetSystemTimeAsFileTime(&filetime);
+ if (RegSetValueExW(hkey, driver_date_dataW, 0, REG_BINARY, (BYTE *)&filetime, sizeof(filetime)))
+ goto done;
+ RegCloseKey(hkey);
+
+ /* Write GUID in VideoID in .../instance/Device Parameters, reuse the GUID if it's existent */
+ hkey = SetupDiCreateDevRegKeyW(devinfo, &device_data, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL);
+
+ size = sizeof(bufferW);
+ if (RegQueryValueExW(hkey, video_idW, 0, NULL, (BYTE *)bufferW, &size))
+ {
+ UuidCreate(&guid);
+ sprintfW(bufferW, guid_fmtW, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
+ guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+ if (RegSetValueExW(hkey, video_idW, 0, REG_SZ, (const BYTE *)bufferW, (lstrlenW(bufferW) + 1) * sizeof(WCHAR)))
+ goto done;
+ }
+
+ ret = TRUE;
+done:
+ RegCloseKey(hkey);
+ if (!ret)
+ ERR("Failed to initialize GPU\n");
+ return ret;
+}
+
+static void prepare_devices(void)
+{
+ static const BOOL not_present = FALSE;
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HDEVINFO devinfo;
+ DWORD i = 0;
+
+ /* FIXME:
+ * Currently SetupDiGetClassDevsW with DIGCF_PRESENT is unsupported, So we need to clean up not present devices in
+ * case application uses SetupDiGetClassDevsW to enumerate devices. Wrong devices could exist in registry as a result
+ * of prefix copying or having devices unplugged. But then we couldn't simply delete GPUs because we need to retain
+ * the same GUID for the same GPU. */
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ if (!SetupDiSetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, DEVPROP_TYPE_BOOLEAN,
+ (const BYTE *)¬_present, sizeof(not_present), 0))
+ ERR("Failed to set GPU present property\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+}
+
+static void cleanup_devices(void)
+{
+ SP_DEVINFO_DATA device_data = {sizeof(device_data)};
+ HDEVINFO devinfo;
+ DWORD type;
+ DWORD i = 0;
+ BOOL present;
+
+ devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, pciW, NULL, 0);
+ while (SetupDiEnumDeviceInfo(devinfo, i++, &device_data))
+ {
+ present = FALSE;
+ SetupDiGetDevicePropertyW(devinfo, &device_data, &DEVPKEY_Device_IsPresent, &type, (BYTE *)&present,
+ sizeof(present), NULL, 0);
+ if (!present && !SetupDiRemoveDevice(devinfo, &device_data))
+ ERR("Failed to remove GPU\n");
+ }
+ SetupDiDestroyDeviceInfoList(devinfo);
+}
+
+/***********************************************************************
+ * macdrv_init_display_devices
+ *
+ * Initialize display device registry data.
+ */
+void macdrv_init_display_devices(void)
+{
+ static const WCHAR init_mutexW[] = {'d','i','s','p','l','a','y','_','d','e','v','i','c','e','_','i','n','i','t',0};
+ HANDLE mutex;
+ struct macdrv_gpu *gpus = NULL;
+ INT gpu_count;
+ INT gpu;
+ HDEVINFO gpu_devinfo = NULL;
+ HKEY video_hkey = NULL;
+ DWORD disposition = 0;
+
+ mutex = CreateMutexW(NULL, FALSE, init_mutexW);
+ WaitForSingleObject(mutex, INFINITE);
+
+ if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, video_keyW, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &video_hkey,
+ &disposition))
+ {
+ ERR("Failed to create video device key\n");
+ goto done;
+ }
+
+ /* Avoid unnecessary reinit */
+ if (disposition != REG_CREATED_NEW_KEY)
+ goto done;
+
+ TRACE("\n");
+
+ prepare_devices();
+
+ gpu_devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_DISPLAY, NULL);
+
+ /* Initialize GPUs */
+ if (macdrv_get_gpus(&gpus, &gpu_count))
+ goto done;
+
+ for (gpu = 0; gpu < gpu_count; gpu++)
+ {
+ if (!macdrv_init_gpu(gpu_devinfo, &gpus[gpu], gpu))
+ goto done;
+ }
+
+done:
+ cleanup_devices();
+ SetupDiDestroyDeviceInfoList(gpu_devinfo);
+ RegCloseKey(video_hkey);
+
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
+
+ macdrv_free_gpus(gpus);
+}
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 8b2f2cb5a3..b9f58b90da 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -223,6 +223,7 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP
extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void check_retina_status(void) DECLSPEC_HIDDEN;
+extern void macdrv_init_display_devices(void) DECLSPEC_HIDDEN;
/**************************************************************************
* Mac IME driver
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 8ca9b9afa0..513746fa0e 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -257,10 +257,27 @@ static inline CGPoint cgpoint_win_from_mac(CGPoint point)
/* display */
+
+/* Represent a physical GPU in the PCI slots */
+struct macdrv_gpu
+{
+ /* PCI GPU io registry entry id */
+ uint64_t id;
+ /* Name, in UTF-8 encoding */
+ char name[128];
+ /* PCI ID */
+ uint32_t vendor_id;
+ uint32_t device_id;
+ uint32_t subsys_id;
+ uint32_t revision_id;
+};
+
extern int macdrv_get_displays(struct macdrv_display** displays, int* count) DECLSPEC_HIDDEN;
extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDEN;
extern int macdrv_set_display_mode(const struct macdrv_display* display,
CGDisplayModeRef display_mode) DECLSPEC_HIDDEN;
+extern int macdrv_get_gpus(struct macdrv_gpu** gpus, int* count) DECLSPEC_HIDDEN;
+extern void macdrv_free_gpus(struct macdrv_gpu* gpus) DECLSPEC_HIDDEN;
/* event */
--
2.15.2 (Apple Git-101.1)
1
0
Aug. 28, 2019
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/wbemprox/qualifier.c | 65 +++++++++++++++++++++++++++++--------
dlls/wbemprox/tests/query.c | 11 +++++++
2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/dlls/wbemprox/qualifier.c b/dlls/wbemprox/qualifier.c
index aa644812f4..d29abd3f38 100644
--- a/dlls/wbemprox/qualifier.c
+++ b/dlls/wbemprox/qualifier.c
@@ -101,19 +101,32 @@ static HRESULT create_qualifier_enum( const WCHAR *class, const WCHAR *member, c
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','_','_','Q','U','A','L',
'I','F','I','E','R','S',' ','W','H','E','R','E',' ','C','l','a','s','s','=',
'\'','%','s','\'',' ','A','N','D',' ','M','e','m','b','e','r','=','\'','%','s','\'',0};
- static const WCHAR noneW[] = {'_','_','N','O','N','E',0};
+ static const WCHAR fmt3W[] =
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','_','_','Q','U','A','L',
+ 'I','F','I','E','R','S',' ','W','H','E','R','E',' ','C','l','a','s','s','=',
+ '\'','%','s','\'',0};
WCHAR *query;
HRESULT hr;
int len;
- if (!member) member = noneW;
- len = lstrlenW( class ) + lstrlenW( member );
- if (name) len += lstrlenW( name ) + ARRAY_SIZE(fmtW);
- else len += ARRAY_SIZE(fmt2W);
-
- if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
- if (name) swprintf( query, len, fmtW, class, member, name );
- else swprintf( query, len, fmt2W, class, member );
+ if (member && name)
+ {
+ len = lstrlenW( class ) + lstrlenW( member ) + lstrlenW( name ) + ARRAY_SIZE(fmtW);
+ if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
+ swprintf( query, len, fmtW, class, member, name );
+ }
+ else if (member)
+ {
+ len = lstrlenW( class ) + lstrlenW( member ) + ARRAY_SIZE(fmt2W);
+ if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
+ swprintf( query, len, fmt2W, class, member );
+ }
+ else
+ {
+ len = lstrlenW( class ) + ARRAY_SIZE(fmt3W);
+ if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
+ swprintf( query, len, fmt3W, class );
+ }
hr = exec_query( query, iter );
heap_free( query );
@@ -123,7 +136,6 @@ static HRESULT create_qualifier_enum( const WCHAR *class, const WCHAR *member, c
static HRESULT get_qualifier_value( const WCHAR *class, const WCHAR *member, const WCHAR *name,
VARIANT *val, LONG *flavor )
{
- static const WCHAR qualifiersW[] = {'_','_','Q','U','A','L','I','F','I','E','R','S',0};
static const WCHAR intvalueW[] = {'I','n','t','e','g','e','r','V','a','l','u','e',0};
static const WCHAR strvalueW[] = {'S','t','r','i','n','g','V','a','l','u','e',0};
static const WCHAR boolvalueW[] = {'B','o','o','l','V','a','l','u','e',0};
@@ -137,7 +149,7 @@ static HRESULT get_qualifier_value( const WCHAR *class, const WCHAR *member, con
hr = create_qualifier_enum( class, member, name, &iter );
if (FAILED( hr )) return hr;
- hr = create_class_object( qualifiersW, iter, 0, NULL, &obj );
+ hr = create_class_object( NULL, iter, 0, NULL, &obj );
IEnumWbemClassObject_Release( iter );
if (FAILED( hr )) return hr;
@@ -179,7 +191,12 @@ static HRESULT WINAPI qualifier_set_Get(
{
struct qualifier_set *set = impl_from_IWbemQualifierSet( iface );
- FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, plFlavor);
+ TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, plFlavor);
+ if (lFlags)
+ {
+ FIXME("flags %08x not supported\n", lFlags);
+ return E_NOTIMPL;
+ }
return get_qualifier_value( set->class, set->member, wszName, pVal, plFlavor );
}
@@ -206,8 +223,28 @@ static HRESULT WINAPI qualifier_set_GetNames(
LONG lFlags,
SAFEARRAY **pNames )
{
- FIXME("%p, %08x, %p\n", iface, lFlags, pNames);
- return E_NOTIMPL;
+ struct qualifier_set *set = impl_from_IWbemQualifierSet( iface );
+ IEnumWbemClassObject *iter;
+ IWbemClassObject *obj;
+ HRESULT hr;
+
+ TRACE("%p, %08x, %p\n", iface, lFlags, pNames);
+ if (lFlags)
+ {
+ FIXME("flags %08x not supported\n", lFlags);
+ return E_NOTIMPL;
+ }
+
+ hr = create_qualifier_enum( set->class, set->member, NULL, &iter );
+ if (FAILED( hr )) return hr;
+
+ hr = create_class_object( NULL, iter, 0, NULL, &obj );
+ IEnumWbemClassObject_Release( iter );
+ if (FAILED( hr )) return hr;
+
+ hr = IWbemClassObject_GetNames( obj, NULL, 0, NULL, pNames );
+ IWbemClassObject_Release( obj );
+ return hr;
}
static HRESULT WINAPI qualifier_set_BeginEnumeration(
diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c
index 162df5418a..b180cfc92f 100644
--- a/dlls/wbemprox/tests/query.c
+++ b/dlls/wbemprox/tests/query.c
@@ -46,6 +46,8 @@ static HRESULT exec_query( IWbemServices *services, const WCHAR *str, IEnumWbemC
for (;;)
{
VARIANT var;
+ IWbemQualifierSet *qualifiers;
+ SAFEARRAY *names;
IEnumWbemClassObject_Next( *result, 10000, 1, &obj, &count );
if (!count) break;
@@ -60,6 +62,15 @@ static HRESULT exec_query( IWbemServices *services, const WCHAR *str, IEnumWbemC
trace("description: %s\n", wine_dbgstr_w(V_BSTR(&var)));
VariantClear( &var );
}
+
+ hr = IWbemClassObject_GetQualifierSet( obj, &qualifiers );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = IWbemQualifierSet_GetNames( qualifiers, 0, &names );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ SafeArrayDestroy( names );
+ IWbemQualifierSet_Release( qualifiers );
IWbemClassObject_Release( obj );
}
}
--
2.20.1
2
1
Aug. 28, 2019
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/LibvirtDomain.pm | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/lib/WineTestBot/LibvirtDomain.pm b/testbot/lib/WineTestBot/LibvirtDomain.pm
index b1e7d1b6..af79e9dd 100644
--- a/testbot/lib/WineTestBot/LibvirtDomain.pm
+++ b/testbot/lib/WineTestBot/LibvirtDomain.pm
@@ -264,7 +264,7 @@ sub _GetStateName($)
{
my ($State) = @_;
- my %StateNames = {
+ my %StateNames = (
Sys::Virt::Domain::STATE_NOSTATE => "no state",
Sys::Virt::Domain::STATE_RUNNING => "running",
Sys::Virt::Domain::STATE_BLOCKED => "blocked",
@@ -273,7 +273,7 @@ sub _GetStateName($)
Sys::Virt::Domain::STATE_SHUTOFF => "shutoff",
Sys::Virt::Domain::STATE_CRASHED => "crashed",
Sys::Virt::Domain::STATE_PMSUSPENDED => "pmsuspended",
- };
+ );
return $StateNames{$State} || "unknown";
}
--
2.20.1
1
0
Aug. 28, 2019
It is useful for testing.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/scripts/SetWinLocale | 2 ++
1 file changed, 2 insertions(+)
diff --git a/testbot/scripts/SetWinLocale b/testbot/scripts/SetWinLocale
index 514f80d0..a6015635 100755
--- a/testbot/scripts/SetWinLocale
+++ b/testbot/scripts/SetWinLocale
@@ -547,6 +547,8 @@ if (defined $Usage)
print " --keyboard KBD Specifies the keyboard layout (see --defaults).\n";
print " --country CTY Specifies the location using only the country part of the\n";
print " Windows locale (see --defaults).\n";
+ print " --no-reboot Do not reboot Windows. Some locale changes will only take\n";
+ print " effect after the next reboot.\n";
print " --debug Show more detailed information about progress.\n";
print " --dry-run Show what would happen but do nothing.\n";
print " --help Shows this usage message.\n";
--
2.20.1
1
0
Aug. 28, 2019
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/wbemprox/tests/query.c | 82 ++++++++++++++++++++++++++++++-------
1 file changed, 68 insertions(+), 14 deletions(-)
diff --git a/dlls/wbemprox/tests/query.c b/dlls/wbemprox/tests/query.c
index 2c1ca7f91d..162df5418a 100644
--- a/dlls/wbemprox/tests/query.c
+++ b/dlls/wbemprox/tests/query.c
@@ -329,7 +329,7 @@ static void _check_property( ULONG line, IWbemClassObject *obj, const WCHAR *pro
static void test_Win32_Bios( IWbemServices *services )
{
static const WCHAR queryW[] =
- {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_', 'B','i','o','s',0};
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_','B','i','o','s',0};
static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR identificationcodeW[] = {'I','d','e','n','t','i','f','i','c','a','t','i','o','n','C','o','d','e',0};
static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
@@ -380,6 +380,57 @@ static void test_Win32_Bios( IWbemServices *services )
SysFreeString( wql );
}
+static void test_Win32_Baseboard( IWbemServices *services )
+{
+ static const WCHAR queryW[] =
+ {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','W','i','n','3','2','_','B','a','s','e','b','o','a','r','d',0};
+ static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
+ static const WCHAR modelW[] = {'M','o','d','e','l',0};
+ static const WCHAR nameW[] = {'N','a','m','e',0};
+ static const WCHAR productW[] = {'P','r','o','d','u','c','t',0};
+ static const WCHAR tagW[] = {'T','a','g',0};
+ static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
+ BSTR wql = SysAllocString( wqlW ), query = SysAllocString( queryW );
+ IEnumWbemClassObject *result;
+ IWbemClassObject *obj;
+ CIMTYPE type;
+ ULONG count;
+ VARIANT val;
+ HRESULT hr;
+
+ hr = IWbemServices_ExecQuery( services, wql, query, 0, NULL, &result );
+ ok( hr == S_OK, "IWbemServices_ExecQuery failed %08x\n", hr );
+
+ hr = IEnumWbemClassObject_Next( result, 10000, 1, &obj, &count );
+ if (hr != S_OK)
+ {
+ win_skip( "Win32_Baseboard not available\n" );
+ return;
+ }
+ ok( hr == S_OK, "IEnumWbemClassObject_Next failed %08x\n", hr );
+
+ check_property( obj, manufacturerW, VT_BSTR, CIM_STRING );
+
+ type = 0xdeadbeef;
+ VariantInit( &val );
+ hr = IWbemClassObject_Get( obj, modelW, 0, &val, &type, NULL );
+ ok( hr == S_OK, "failed to get model %08x\n", hr );
+ ok( V_VT( &val ) == VT_BSTR || V_VT( &val ) == VT_NULL, "unexpected variant type 0x%x\n", V_VT( &val ) );
+ ok( type == CIM_STRING, "unexpected type 0x%x\n", type );
+ trace( "model: %s\n", wine_dbgstr_w(V_BSTR(&val)) );
+ VariantClear( &val );
+
+ check_property( obj, nameW, VT_BSTR, CIM_STRING );
+ check_property( obj, productW, VT_BSTR, CIM_STRING );
+ check_property( obj, tagW, VT_BSTR, CIM_STRING );
+ check_property( obj, versionW, VT_BSTR, CIM_STRING );
+
+ IWbemClassObject_Release( obj );
+ IEnumWbemClassObject_Release( result );
+ SysFreeString( query );
+ SysFreeString( wql );
+}
+
static void test_Win32_Process( IWbemServices *services, BOOL use_full_path )
{
static const WCHAR returnvalueW[] = {'R','e','t','u','r','n','V','a','l','u','e',0};
@@ -1591,28 +1642,31 @@ START_TEST(query)
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
ok( hr == S_OK, "failed to set proxy blanket %08x\n", hr );
- test_select( services );
+ test_GetNames( services );
test_associators( services );
- test_Win32_Bios( services );
- test_Win32_Process( services, FALSE );
- test_Win32_Process( services, TRUE );
- test_Win32_Service( services );
- test_Win32_ComputerSystem( services );
- test_Win32_SystemEnclosure( services );
- test_StdRegProv( services );
test_notification_query_async( services );
test_query_async( services );
test_query_semisync( services );
- test_GetNames( services );
+ test_select( services );
+
+ /* classes */
+ test_StdRegProv( services );
test_SystemSecurity( services );
- test_Win32_OperatingSystem( services );
+ test_Win32_Baseboard( services );
+ test_Win32_ComputerSystem( services );
test_Win32_ComputerSystemProduct( services );
- test_Win32_PhysicalMemory( services );
+ test_Win32_Bios( services );
test_Win32_IP4RouteTable( services );
+ test_Win32_OperatingSystem( services );
+ test_Win32_PhysicalMemory( services );
+ test_Win32_PnPEntity( services );
+ test_Win32_Printer( services );
+ test_Win32_Process( services, FALSE );
+ test_Win32_Process( services, TRUE );
test_Win32_Processor( services );
+ test_Win32_Service( services );
+ test_Win32_SystemEnclosure( services );
test_Win32_VideoController( services );
- test_Win32_Printer( services );
- test_Win32_PnPEntity( services );
SysFreeString( path );
IWbemServices_Release( services );
--
2.20.1
2
1