@@ -90,8 +90,9 @@ wstring confpath = L"C:\\VirtualDisplayDriver";
9090bool logsEnabled = false ;
9191bool debugLogs;
9292bool HDRPlus = false ;
93+ bool customEdid = false ;
9394
94-
95+ vector< unsigned char > Microsoft::IndirectDisp::IndirectDeviceContext::s_KnownMonitorEdid; // Changed to support static vector
9596
9697struct IndirectDeviceContextWrapper
9798{
@@ -454,6 +455,108 @@ bool HDRPLUSEnabledQuery() {
454455 return xmlHDRvalue;
455456}
456457
458+
459+ bool CustomEdidEnabledQuery () {
460+ wstring settingsname = confpath + L" \\ vdd_settings.xml" ;
461+ HKEY hKey;
462+ DWORD dwValue;
463+ DWORD dwBufferSize = sizeof (dwValue);
464+ LONG lResult = RegOpenKeyExW (HKEY_LOCAL_MACHINE , L" SOFTWARE\\ MikeTheTech\\ VirtualDisplayDriver" , 0 , KEY_READ , &hKey);
465+
466+ if (lResult == ERROR_SUCCESS ) {
467+ vddlog (" d" , " Get CustomEdid - Successfully opened registry key." );
468+
469+ lResult = RegQueryValueExW (hKey, L" CUSTOMEDID" , NULL , NULL , (LPBYTE )&dwValue, &dwBufferSize);
470+ if (lResult == ERROR_SUCCESS ) {
471+ RegCloseKey (hKey);
472+ vddlog (" d" , " Get CustomEdid - CustomEdid value retrieved from registry." );
473+
474+ if (dwValue == 1 ) {
475+ vddlog (" d" , " Get CustomEdid - CustomEdid is enabled (value = 1)." );
476+ return true ;
477+ }
478+ else if (dwValue == 0 ) {
479+ vddlog (" d" , " Get CustomEdid - CustomEdid is disabled (value = 0). Checking XML settings." );
480+ goto check_xml;
481+ }
482+ }
483+ else {
484+ vddlog (" e" , " Get CustomEdid - Failed to retrieve CustomEdid value from registry. Attempting to read as string." );
485+ wchar_t path[MAX_PATH ];
486+ dwBufferSize = sizeof (path);
487+ lResult = RegQueryValueExW (hKey, L" CUSTOMEDID" , NULL , NULL , (LPBYTE )path, &dwBufferSize);
488+
489+ if (lResult == ERROR_SUCCESS ) {
490+ wstring CustomEdidValue (path);
491+ RegCloseKey (hKey);
492+ vddlog (" d" , " Get CustomEdid - CustomEdid string value retrieved from registry. " );
493+
494+ if (CustomEdidValue == L" true" || CustomEdidValue == L" 1" ) {
495+ vddlog (" d" , " Get CustomEdid - CustomEdid is enabled (string value)." );
496+ return true ;
497+ }
498+ else if (CustomEdidValue == L" false" || CustomEdidValue == L" 0" ) {
499+ vddlog (" d" , " Get CustomEdid - CustomEdid is disabled (string value). Checking XML settings." );
500+ goto check_xml;
501+ }
502+ }
503+ RegCloseKey (hKey);
504+ vddlog (" e" , " Get CustomEdid - Failed to retrieve CustomEdid string value from registry." );
505+ }
506+ }
507+ else {
508+ vddlog (" e" , " Get CustomEdid - Failed to open registry key for CustomEdid." );
509+ }
510+
511+ check_xml:
512+ CComPtr<IStream> pFileStream;
513+ HRESULT hr = SHCreateStreamOnFileEx (settingsname.c_str (), STGM_READ , FILE_ATTRIBUTE_NORMAL , FALSE , nullptr , &pFileStream);
514+
515+ if (FAILED (hr)) {
516+ vddlog (" e" , " Get CustomEdid - Failed to create file stream for XML settings." );
517+ return false ;
518+ }
519+ vddlog (" d" , " Get CustomEdid - File stream created for XML settings." );
520+
521+ CComPtr<IXmlReader> pReader;
522+ hr = CreateXmlReader (__uuidof (IXmlReader), (void **)&pReader, nullptr );
523+
524+ if (FAILED (hr)) {
525+ vddlog (" e" , " Get CustomEdid - Failed to create XML reader." );
526+ return false ;
527+ }
528+ vddlog (" d" , " Get CustomEdid - XML reader created." );
529+
530+ hr = pReader->SetInput (pFileStream);
531+ if (FAILED (hr)) {
532+ vddlog (" e" , " Get CustomEdid - Failed to set input for XML reader." );
533+ return false ;
534+ }
535+ vddlog (" d" , " Get CustomEdid - Input set for XML reader." );
536+
537+ XmlNodeType nodeType;
538+ const wchar_t * pwszLocalName;
539+ bool xmlCustomEdidvalue = false ;
540+
541+ while (S_OK == pReader->Read (&nodeType)) {
542+ if (nodeType == XmlNodeType_Element) {
543+ pReader->GetLocalName (&pwszLocalName, nullptr );
544+ if (wcscmp (pwszLocalName, L" CustomEdid" ) == 0 ) {
545+ pReader->Read (&nodeType);
546+ if (nodeType == XmlNodeType_Text) {
547+ const wchar_t * pwszValue;
548+ pReader->GetValue (&pwszValue, nullptr );
549+ xmlCustomEdidvalue = (wcscmp (pwszValue, L" true" ) == 0 );
550+ vddlog (" i" , xmlCustomEdidvalue ? " CustomEdid is enabled." : " CustomEdid is disabled." );
551+ break ;
552+ }
553+ }
554+ }
555+ }
556+
557+ return xmlCustomEdidvalue;
558+ }
559+
457560void LogIddCxVersion () {
458561 IDARG_OUT_GETVERSION outArgs;
459562 NTSTATUS status = IddCxGetVersion (&outArgs);
@@ -911,6 +1014,7 @@ extern "C" NTSTATUS DriverEntry(
9111014 initpath ();
9121015 logsEnabled = LogEnabledQuery ();
9131016 HDRPlus = HDRPLUSEnabledQuery ();
1017+ customEdid = CustomEdidEnabledQuery ();
9141018 vddlog (" i" , " Driver Starting" );
9151019 string utf8_confpath = WStringToString (confpath);
9161020 string logtext = " VDD Path: " + utf8_confpath;
@@ -1702,8 +1806,7 @@ constexpr DISPLAYCONFIG_VIDEO_SIGNAL_INFO dispinfo(UINT32 h, UINT32 v, UINT32 r)
17021806 };
17031807}
17041808
1705- // This is a sample monitor EDID - FOR SAMPLE PURPOSES ONLY
1706- const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] =
1809+ vector<BYTE > hardcodedEdid =
17071810{
170818110x00 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0x00 , 0x36 , 0x94 , 0x37 , 0x13 , 0xe7 , 0x1e , 0xe7 , 0x1e ,
170918120x1c , 0x22 , 0x01 , 0x03 , 0x80 , 0x32 , 0x1f , 0x78 , 0x07 , 0xee , 0x95 , 0xa3 , 0x54 , 0x4c , 0x99 , 0x26 ,
@@ -1723,6 +1826,85 @@ const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] =
172318260x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x8c
17241827};
17251828
1829+
1830+ void modifyEdid (vector<BYTE >& edid) {
1831+ if (edid.size () < 12 ) {
1832+ return ;
1833+ }
1834+
1835+ edid[8 ] = 0x36 ;
1836+ edid[9 ] = 0x94 ;
1837+ edid[10 ] = 0x37 ;
1838+ edid[11 ] = 0x13 ;
1839+ }
1840+
1841+
1842+
1843+ BYTE calculateChecksum (const std::vector<BYTE >& edid) {
1844+ int sum = 0 ;
1845+ for (int i = 0 ; i < 127 ; ++i) {
1846+ sum += edid[i];
1847+ }
1848+ sum %= 256 ;
1849+ if (sum != 0 ) {
1850+ sum = 256 - sum;
1851+ }
1852+ return static_cast <BYTE >(sum);
1853+ // check sum calculations. We dont need to include old checksum in calculation, so we only read up to the byte before.
1854+ // Anything after the checksum bytes arent part of the checksum - a flaw with edid managment, not with us
1855+ }
1856+
1857+ vector<BYTE > loadEdid (const string& filePath) {
1858+ if (customEdid) {
1859+ vddlog (" i" , " Attempting to use user Edid" );
1860+ }
1861+ else {
1862+ vddlog (" i" , " Using hardcoded edid" );
1863+ return hardcodedEdid;
1864+ }
1865+
1866+
1867+ ifstream file (filePath, ios::binary | ios::ate);
1868+ if (!file) {
1869+ vddlog (" i" , " No custom edid found" );
1870+ vddlog (" i" , " Using hardcoded edid" );
1871+ return hardcodedEdid;
1872+ }
1873+
1874+ streamsize size = file.tellg ();
1875+ file.seekg (0 , ios::beg);
1876+
1877+ vector<BYTE > buffer (size);
1878+ if (file.read ((char *)buffer.data (), size)) {
1879+ // calculate checksum and compare it to 127 byte, if false then return hardcoded if true then return buffer to prevent loading borked edid.
1880+ BYTE calculatedChecksum = calculateChecksum (buffer);
1881+ if (calculatedChecksum != buffer[127 ]) {
1882+ vddlog (" e" , " Custom edid failed due to invalid checksum" );
1883+ vddlog (" i" , " Using hardcoded edid" );
1884+ return hardcodedEdid;
1885+ }
1886+ vddlog (" i" , " Using custom edid" );
1887+ return buffer;
1888+ }
1889+ else {
1890+ vddlog (" i" , " Using hardcoded edid" );
1891+ return hardcodedEdid;
1892+ }
1893+ }
1894+
1895+ int maincalc () {
1896+ vector<BYTE > edid = loadEdid (WStringToString (confpath) + " \\ user_edid.bin" );
1897+
1898+ modifyEdid (edid);
1899+ BYTE checksum = calculateChecksum (edid);
1900+ edid[127 ] = checksum;
1901+ // Setting this variable is depricated, hardcoded edid is either returned or custom in loading edid function
1902+ IndirectDeviceContext::s_KnownMonitorEdid = edid;
1903+ return 0 ;
1904+ }
1905+
1906+
1907+
17261908IndirectDeviceContext::IndirectDeviceContext (_In_ WDFDEVICE WdfDevice) :
17271909 m_WdfDevice(WdfDevice)
17281910{
@@ -1747,6 +1929,7 @@ IndirectDeviceContext::~IndirectDeviceContext()
17471929
17481930void IndirectDeviceContext::InitAdapter ()
17491931{
1932+ maincalc ();
17501933 stringstream logStream;
17511934
17521935 // ==============================
@@ -1864,8 +2047,25 @@ void IndirectDeviceContext::CreateMonitor(unsigned int index) {
18642047 MonitorInfo.ConnectorIndex = index;
18652048 MonitorInfo.MonitorDescription .Size = sizeof (MonitorInfo.MonitorDescription );
18662049 MonitorInfo.MonitorDescription .Type = IDDCX_MONITOR_DESCRIPTION_TYPE_EDID ;
1867- MonitorInfo.MonitorDescription .DataSize = sizeof (s_KnownMonitorEdid);
1868- MonitorInfo.MonitorDescription .pData = const_cast <BYTE *>(s_KnownMonitorEdid);
2050+ // MonitorInfo.MonitorDescription.DataSize = sizeof(s_KnownMonitorEdid); can no longer use size of as converted to vector
2051+ if (s_KnownMonitorEdid.size () > UINT_MAX )
2052+ {
2053+ vddlog (" e" , " Edid size passes UINT_Max, escape to prevent loading borked display" );
2054+ }
2055+ else
2056+ {
2057+ MonitorInfo.MonitorDescription .DataSize = static_cast <UINT >(s_KnownMonitorEdid.size ());
2058+ }
2059+ // MonitorInfo.MonitorDescription.pData = const_cast<BYTE*>(s_KnownMonitorEdid);
2060+ // Changed from using const_cast to data() to safely access the EDID data.
2061+ // This improves type safety and code readability, as it eliminates the need for casting
2062+ // and ensures we are directly working with the underlying container of known monitor EDID data.
2063+ MonitorInfo.MonitorDescription .pData = IndirectDeviceContext::s_KnownMonitorEdid.data ();
2064+
2065+
2066+
2067+
2068+
18692069
18702070 // ==============================
18712071 // TODO: The monitor's container ID should be distinct from "this" device's container ID if the monitor is not
0 commit comments