You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Once upon a time I had an impossible to ignore urge to read EDIDs of all connected displays on Windows. In bare C and WinAPI only.
Expectation: There's a function likeGetEdidForMonitor(HMONITOR)
Reality: One does not simply. There are no officially documented ways to do this, no fully working code examples, and no, LLMs couldn't conjure one up either (although they did provide valuable research pointers).
A brief sequence of events
CallEnumDisplayMonitors() (масло масляное) to receive a bunch ofHMONITOR handles for each connected display.
GetMonitorInfo() to getMONITORINFOEX.szDevice will contain display device name like\\.\DISPLAY14.
UseEnumDisplayDevices(szDevice, EDD_GET_DEVICE_INTERFACE_NAME) to getDISPLAY_DEVICE.DeviceID containing device path like\\?\DISPLAY#LKG001A#5&272c5422&0&UID513#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
UseSetupDiGetClassDevs(GUID_DEVINTERFACE_MONITOR, DIGCF_DEVICEINTERFACE) to request a set of all monitor-class devices interfaces.
Enumerate the set usingSetupDiEnumDeviceInterfaces(set, GUID_DEVINTERFACE_MONITOR, index), gettingSP_DEVICE_INTERFACE_DATA
For each interface retrieveSP_INTERFACE_DEVICE_DETAIL_DATA usingSetupDiGetDeviceInterfaceDetail(set, iface_data). It's a three-step process. First, get the detail struct size, then allocate it, then call the function again to fill the detail data. Also, use this function to readSP_DEVINFO_DATA.
Comparedetail.DevicePath with the device pathDISPLAY_DEVICE.DeviceID from step 3. Note that they will have different case, so case-insensitive comparison is needed. If they match, then you've found associated interface for theHMONITOR from step 1.
UseSetupDiOpenDevRegKey(set, devinfo_data) to open registry key. (Yes, the regedit-registry. No, it's not practical to guess the key, it's something likeHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY\CMN152A\5&272c5422&0&UID512\Device Parameters and seems unstable)
UseRegQueryValueEx(key, "EDID") to read EDID value data into buffer of 128 bytes. No, it won't read past 128 bytes to get extensions, e.g. for CEC.
If nothing failed, you're done. Time to cleanup all this mess. Maybe the real treasure was all the handles we created and memory we allocated along the way.
Bonus One
The example code also reads monitor positions and current modes, so that there's association between EDID and virtual display geometry.
No, I haven't found an easy read monitor names (e.g. vendor, model). I haven't really looked, though.
Bonus Two
This repo contains some cmake configuration to manifest this app into a DPI-aware world. Without this, the bonus one code would read dpi-unaware (scaled) monitor positions, which might be not what you want.
Appendix
How to read EDID in X11:
XRRGetScreenResources() to get resources.
For eachresources->output[i]: useXRRGetOutputProperty(output, XInternAtom("EDID")), done.
About
Enumerate displays and read EDID on Windows using C, WinAPI, and luck 🍀