Skip to content

Commit 53aa27a

Browse files
committed
Refactor EDID retrieval and parsing logic
1 parent 010066f commit 53aa27a

File tree

1 file changed

+93
-45
lines changed

1 file changed

+93
-45
lines changed

libnw/display.c

Lines changed: 93 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -655,15 +655,12 @@ static void DecodeEstablishedTimings(const BYTE* edid, PNODE node)
655655
}
656656
}
657657

658-
static void DecodeEdid(const BYTE* edidData, DWORD edidSize, PNODE nm, CHAR* ids, DWORD idsSize)
658+
static void DecodeEdid(const BYTE* edidData, DWORD edidSize, PNODE nm, CHAR* ids, DWORD idsSize, const WCHAR* hwId)
659659
{
660660
struct MONITOR_INFO mi = { 0 };
661661
// An EDID block must be at least 128 bytes.
662662
if (edidSize < 128)
663-
{
664-
NWL_NodeAppendMultiSz(&NWLC->ErrLog, "Invalid EDID size");
665663
return;
666-
}
667664

668665
// Verify checksum of the base block. The sum of all 128 bytes must be a multiple of 256.
669666
BYTE checksum = 0;
@@ -701,6 +698,7 @@ static void DecodeEdid(const BYTE* edidData, DWORD edidSize, PNODE nm, CHAR* id
701698
mi.Height = 10ULL * edidData[22];
702699
snprintf(mi.Serial, sizeof(mi.Serial), "%08X", serialNumber);
703700

701+
NWL_NodeAttrSet(nm, "HWID", NWL_Ucs2ToUtf8(hwId), 0);
704702
NWL_NodeAttrSetf(nm, "ID", 0, "%s%04X", vendorId, productCode);
705703
NWL_GetPnpManufacturer(nm, ids, idsSize, vendorId);
706704
NWL_NodeAttrSetf(nm, "EDID Version", 0, "%d.%d", edidMajor, edidMinor);
@@ -773,46 +771,85 @@ static void DecodeEdid(const BYTE* edidData, DWORD edidSize, PNODE nm, CHAR* id
773771
// Note: Parsing of extension blocks (e.g., CTA-861) is not implemented here.
774772
}
775773

776-
static void
777-
GetEdid(PNODE node, HDEVINFO devInfo, PSP_DEVINFO_DATA devInfoData, CHAR* ids, DWORD idsSize, DWORD index)
774+
static BOOL
775+
GetMonitorEdid(HDEVINFO hDevInfo, int idxMonitor, BYTE** edidData, DWORD* edidSize, WCHAR** hwId)
778776
{
779-
HKEY hDevRegKey;
780-
LSTATUS lRet;
781-
UCHAR* edidData = NWLC->NwBuf;
782-
DWORD edidSize;
783-
784-
if (!SetupDiGetDeviceRegistryPropertyW(devInfo, devInfoData,
785-
SPDRP_HARDWAREID, NULL, (PBYTE)NWLC->NwBufW, NWINFO_BUFSZB, NULL))
786-
return;
777+
*edidData = NULL;
778+
*edidSize = 0;
779+
*hwId = NULL;
780+
781+
BOOL rc = FALSE;
782+
SP_DEVINFO_DATA devInfoData;
783+
devInfoData.cbSize = sizeof(devInfoData);
784+
785+
// Enumerate the monitor devices.
786+
if (!SetupDiEnumDeviceInfo(hDevInfo, idxMonitor, &devInfoData))
787+
goto fail;
788+
rc = TRUE;
789+
790+
// Get Hardware ID for the monitor
791+
DWORD hwidSize = 0;
792+
SetupDiGetDeviceRegistryPropertyW(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, NULL, 0, &hwidSize);
793+
if (hwidSize > 0)
794+
{
795+
*hwId = (WCHAR*)malloc(hwidSize);
796+
if (*hwId)
797+
{
798+
if (!SetupDiGetDeviceRegistryPropertyW(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, (PBYTE)*hwId, hwidSize, NULL))
799+
{
800+
free(*hwId);
801+
*hwId = NULL;
802+
}
803+
}
804+
}
787805

788-
if (NWLC->NwOsInfo.dwMajorVersion <= 5)
806+
// Windows XP: prevent duplicate entries
807+
if (NWLC->NwOsInfo.dwMajorVersion <= 5 && *hwId)
789808
{
790-
// Windows XP: prevent duplicate entries
791-
static WCHAR savedHwid[32] = { 0 };
792-
if (index && wcscmp(savedHwid, NWLC->NwBufW) == 0)
793-
return;
794-
wcscpy_s(savedHwid, 32, NWLC->NwBufW);
809+
static WCHAR cachedHwId[32] = { 0 };
810+
if (idxMonitor && wcscmp(cachedHwId, *hwId) == 0)
811+
goto fail;
812+
wcscpy_s(cachedHwId, ARRAYSIZE(cachedHwId), *hwId);
795813
}
796814

797-
PNODE nm = NWL_NodeAppendNew(node, "Monitor", NFLG_TABLE_ROW);
798-
NWL_NodeAttrSet(nm, "HWID", NWL_Ucs2ToUtf8(NWLC->NwBufW), 0);
815+
// Open the device's registry key.
816+
HKEY devRegKey = SetupDiOpenDevRegKey(hDevInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
817+
if (devRegKey == INVALID_HANDLE_VALUE)
818+
goto fail;
799819

800-
hDevRegKey = SetupDiOpenDevRegKey(devInfo, devInfoData,
801-
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_ALL_ACCESS);
820+
// Query for the size of the EDID data.
821+
DWORD dwType;
822+
DWORD dwSize = 0;
823+
if (RegQueryValueExW(devRegKey, L"EDID", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
824+
goto fail;
802825

803-
if (!hDevRegKey)
804-
{
805-
NWL_NodeAppendMultiSz(&NWLC->ErrLog, "SetupDiOpenDevRegKey failed");
806-
return;
807-
}
808-
edidSize = NWINFO_BUFSZ;
809-
ZeroMemory(edidData, edidSize);
810-
lRet = RegGetValueW(hDevRegKey, NULL, L"EDID", RRF_RT_REG_BINARY, NULL, edidData, &edidSize);
811-
if (lRet == ERROR_SUCCESS || lRet == ERROR_MORE_DATA)
812-
{
813-
DecodeEdid(edidData, edidSize, nm, ids, idsSize);
814-
}
815-
RegCloseKey(hDevRegKey);
826+
// Allocate a buffer and query the actual EDID data.
827+
*edidData = (BYTE*)malloc(dwSize);
828+
if (!*edidData)
829+
goto fail;
830+
831+
LSTATUS lResult = RegQueryValueExW(devRegKey, L"EDID", NULL, &dwType, *edidData, &dwSize);
832+
833+
RegCloseKey(devRegKey);
834+
835+
if (lResult != ERROR_SUCCESS)
836+
goto fail;
837+
838+
if (dwType != REG_BINARY || dwSize < 128)
839+
goto fail;
840+
841+
*edidSize = dwSize;
842+
return rc;
843+
844+
fail:
845+
if (*edidData)
846+
free(*edidData);
847+
*edidData = NULL;
848+
*edidSize = 0;
849+
if (*hwId)
850+
free(*hwId);
851+
*hwId = NULL;
852+
return rc;
816853
}
817854

818855
static VOID
@@ -872,27 +909,38 @@ NWL_GetCurDisplay(HWND wnd, NWLIB_CUR_DISPLAY* info)
872909
PNODE NW_Edid(VOID)
873910
{
874911
PNODE node = NWL_NodeAlloc("Display", NFLG_TABLE);
875-
HDEVINFO hdevInfo = NULL;
876912
DWORD i = 0;
877-
SP_DEVINFO_DATA devInfoData = { .cbSize = sizeof(SP_DEVINFO_DATA) };
878-
DWORD dwFlags = DIGCF_PRESENT | DIGCF_DEVICEINTERFACE;
879913
CHAR* ids = NULL;
880914
DWORD idsSize = 0;
915+
HDEVINFO hDevInfo = NULL;
881916
if (NWLC->EdidInfo)
882917
NWL_NodeAppendChild(NWLC->NwRoot, node);
883918

884-
hdevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MONITOR, NULL, NULL, dwFlags);
885-
if (hdevInfo == INVALID_HANDLE_VALUE)
919+
hDevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_MONITOR, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
920+
if (hDevInfo == INVALID_HANDLE_VALUE)
886921
{
887922
NWL_NodeAppendMultiSz(&NWLC->ErrLog, "SetupDiGetClassDevs failed");
888923
goto disp;
889924
}
925+
890926
ids = NWL_LoadIdsToMemory(L"pnp.ids", &idsSize);
891-
for (i = 0; SetupDiEnumDeviceInfo(hdevInfo, i, &devInfoData); i++)
927+
for (i = 0; ; i++)
892928
{
893-
GetEdid(node, hdevInfo, &devInfoData, ids, idsSize, i);
929+
BYTE* edidData = NULL;
930+
DWORD edidSize = 0;
931+
WCHAR* hwId = NULL;
932+
933+
if (!GetMonitorEdid(hDevInfo, i, &edidData, &edidSize, &hwId))
934+
break;
935+
if (!edidData)
936+
continue;
937+
PNODE nm = NWL_NodeAppendNew(node, "Monitor", NFLG_TABLE_ROW);
938+
DecodeEdid(edidData, edidSize, nm, ids, idsSize, hwId);
939+
NWL_NodeAttrSetRaw(nm, "Binary Data", edidData, (size_t)edidSize);
940+
free(edidData);
941+
free(hwId);
894942
}
895-
SetupDiDestroyDeviceInfoList(hdevInfo);
943+
SetupDiDestroyDeviceInfoList(hDevInfo);
896944
free(ids);
897945
disp:
898946
EnumDisp(node);

0 commit comments

Comments
 (0)