@@ -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
818855static VOID
@@ -872,27 +909,38 @@ NWL_GetCurDisplay(HWND wnd, NWLIB_CUR_DISPLAY* info)
872909PNODE 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 );
897945disp :
898946 EnumDisp (node );
0 commit comments