Skip to content

Commit 2d37496

Browse files
author
Bud
committed
Custom Edid Support
- Added custom edid support - Toggle edid in xml or master in registry - Live edid modification to easily identify emulated displays - Checksum checks to make sure data isn't corrupt - Converted edid to static vector instead to allow custom edid
1 parent 2bfbb0e commit 2d37496

3 files changed

Lines changed: 207 additions & 6 deletions

File tree

Virtual Display Driver (HDR)/MttVDD/Driver.cpp

Lines changed: 205 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ wstring confpath = L"C:\\VirtualDisplayDriver";
9090
bool logsEnabled = false;
9191
bool debugLogs;
9292
bool HDRPlus = false;
93+
bool customEdid = false;
9394

94-
95+
vector<unsigned char> Microsoft::IndirectDisp::IndirectDeviceContext::s_KnownMonitorEdid; //Changed to support static vector
9596

9697
struct 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+
457560
void 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
{
17081811
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x36, 0x94, 0x37, 0x13, 0xe7, 0x1e, 0xe7, 0x1e,
17091812
0x1c, 0x22, 0x01, 0x03, 0x80, 0x32, 0x1f, 0x78, 0x07, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26,
@@ -1723,6 +1826,85 @@ const BYTE IndirectDeviceContext::s_KnownMonitorEdid[] =
17231826
0x00, 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+
17261908
IndirectDeviceContext::IndirectDeviceContext(_In_ WDFDEVICE WdfDevice) :
17271909
m_WdfDevice(WdfDevice)
17281910
{
@@ -1747,6 +1929,7 @@ IndirectDeviceContext::~IndirectDeviceContext()
17471929

17481930
void 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

Virtual Display Driver (HDR)/MttVDD/Driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ namespace Microsoft
100100

101101
public:
102102
static const DISPLAYCONFIG_VIDEO_SIGNAL_INFO s_KnownMonitorModes[];
103-
static const BYTE s_KnownMonitorEdid[];
103+
static std::vector<BYTE> s_KnownMonitorEdid;
104104
};
105105
}
106106
}

Virtual Display Driver (HDR)/vdd_settings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161

6262
</resolutions>
6363
<options>
64+
<CustomEdid>false</CustomEdid> <!-- Custom Edid should be named "user_edid.bin"! This does not support emulating resolutions!-->
6465
<HDRPlus>false</HDRPlus>
6566
<logging>false</logging>
6667
<!-- DEBUG LOGGING FOR EXPERTS ONLY!-->

0 commit comments

Comments
 (0)