I need help in associating PHYSICAL_MONITOR which i get from GetPhysicalMonitorsFromHMONITOR with monitors DISPLAY_DEVICE.DeviceID (e.g. "\?\DISPLAY#GSM59AB#5&932a802&1&UID261#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"), which is from EnumDisplayDevices used with flag EDD_GET_DEVICE_INTERFACE_NAME, or somehow get PHYSICAL_MONITOR from DISPLAY_DEVICE.DeviceID or vice versa.
I need both of them associated because:
HANDLE PHYSICAL_MONITOR.hPhysicalMonitor will be used for lowlevelmonitorconfigurationapi because i need to send commands to monitors.
DISPLAY_DEVICE.DeviceID is used to get EDID structure from registry (first 128 bytes are enough for me , need only manufacturer code and model) using SetupAPI
1 and 2 are done, the problem is associating id with physical monitor. Also it is possible to get all monitors EDIDs from registry using only SetupAPI, but in this case it is impossible to get physical monitors HANDLEs.
Same question on MSDN, not solved((
Also i noticed one thing: This code enumerates all monitors:
DWORD DispNum = 0;
DISPLAY_DEVICE DisplayDevice;
// Initialize DisplayDevice.
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);
while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)))
{
std::wstring deviceName = DisplayDevice.DeviceName;
DISPLAY_DEVICE DisplayDeviceM;
ZeroMemory(&DisplayDeviceM, sizeof(DisplayDeviceM));
DisplayDeviceM.cb = sizeof(DisplayDeviceM);
int monitorIndex = 0;
while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &DisplayDeviceM, EDD_GET_DEVICE_INTERFACE_NAME))
{
std::wstring monitorID = DisplayDeviceM.DeviceID;
++monitorIndex;
}
DispNum++;
}
In the same order as this one:
BOOL CALLBACK EnumProc2(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
LPPHYSICAL_MONITOR pMons = NULL;
DWORD i, mcnt;
MONITORINFOEX mi;
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
DISPLAY_DEVICE dd;
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
EnumDisplayDevices(mi.szDevice, 0, &dd, EDD_GET_DEVICE_INTERFACE_NAME);
monitorModelMnufac MdlManuf = findMonitorModelManufactFromEDID(dd.DeviceID);
if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &mcnt)) return TRUE;
pMons = (LPPHYSICAL_MONITOR)malloc(mcnt * sizeof(PHYSICAL_MONITOR));
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, mcnt, pMons))
for (i = 0; i < mcnt; i++)
{
AddToMonHandles(pMons[i].hPhysicalMonitor, MdlManuf);
}
free(pMons);
return TRUE;
}
And physical monitors HANDLEs are 0,1,2 and so on, so i can make HANDLEs from "monitorIndex" but i'm not sure if doing like that is secure.
I also looked in registry to find physical monitors HANDLEs, but nothing there.
Also found function which is helpful VideoPortDDCMonitorHelper but as i googled, it need to be used in driver/filter and can't be used from a simple executable.
Also tried to reverse windows dlls, all calls seems to be made from WIN32U.dll and Ghidra doesn't want to decompile it, or i'm just noob at that.
Please help me guys :)
I've looked for a connection between
EnumDisplayDevices
andGetPhysicalMonitorsFromHMONITOR
for somewhat similar purposes; I need a unique ID for each monitor, plus the ability to set a VCP value.Some related posts don't give me confidence there's a simple answer.
I'm not sure if it's of any help, but I found ControlMyMonitor to be useful.
Running:
Produces info for each monitor:
And you can set VCP values easily. For example, tell the monitor to change to HDMI 1:
Also, if you call
EnumDisplayMonitors
in order to getPHYSICAL_MONITOR.hPhysicalMonitor
, then you pass that handle toCapabilitiesRequestAndCapabilitiesReply
, it produces this output:Which happens to contain the model number.
Hopefully some information produced by the above commands helps you toward your goal.
Good luck!