diff options
Diffstat (limited to 'src/newt/native/WindowsEDID.c')
-rw-r--r-- | src/newt/native/WindowsEDID.c | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/src/newt/native/WindowsEDID.c b/src/newt/native/WindowsEDID.c new file mode 100644 index 000000000..d84773dc6 --- /dev/null +++ b/src/newt/native/WindowsEDID.c @@ -0,0 +1,419 @@ +/** + * Copyright 2015 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + * + *** + * + * This code is inspired by Ofek Shilon's code and blog post: + * <http://ofekshilon.com/2014/06/19/reading-specific-monitor-dimensions/> + * See: function 'NewtEDID_GetMonitorSizeFromEDIDByModelName' + * + * In contrast to Ofek's code, function 'NewtEDID_GetMonitorSizeFromEDIDByDevice' + * uses the proper link from + * DISPLAY_DEVICE.DeviceID -> SP_DEVICE_INTERFACE_DETAIL_DATA.DevicePath, + * where DISPLAY_DEVICE.DeviceID is the monitor's enumeration via: + * EnumDisplayDevices(adapterName, monitor_idx, &ddMon, EDD_GET_DEVICE_INTERFACE_NAME); + * Hence the path to the registry-entry is well determined instead of just comparing + * the monitor's model name. + * + */ + +#include <Windows.h> +#include <Windowsx.h> +#include <tchar.h> +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> + +#include <SetupApi.h> +#include <cfgmgr32.h> // for MAX_DEVICE_ID_LEN + +#include "WindowsEDID.h" + +// #define VERBOSE_ON 1 + +#ifdef VERBOSE_ON + #define DBG_PRINT(x, ...) _ftprintf(stderr, __T(x), ##__VA_ARGS__); fflush(stderr) +#else + #define DBG_PRINT(...) +#endif + +#define NAME_SIZE 128 + +/* GetProcAddress doesn't exist in A/W variants under desktop Windows */ +#ifndef UNDER_CE +#define GetProcAddressA GetProcAddress +#endif + +#ifndef EDD_GET_DEVICE_INTERFACE_NAME +#define EDD_GET_DEVICE_INTERFACE_NAME 0x00000001 +#endif + +static const GUID GUID_CLASS_MONITOR = { 0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 }; +static const GUID GUID_DEVINTERFACE_MONITOR = { 0xe6f07b5f, 0xee97, 0x4a90, 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7 }; + +#ifdef _UNICODE +typedef HDEVINFO (WINAPI *SetupDiGetClassDevsPROCADDR)(CONST GUID *ClassGuid,PCWSTR Enumerator,HWND hwndParent,DWORD Flags); +typedef WINBOOL (WINAPI *SetupDiGetDeviceInstanceIdPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,PCWSTR DeviceInstanceId,DWORD DeviceInstanceIdSize,PDWORD RequiredSize); +typedef WINBOOL (WINAPI *SetupDiGetDeviceInterfaceDetailPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,DWORD DeviceInterfaceDetailDataSize,PDWORD RequiredSize,PSP_DEVINFO_DATA DeviceInfoData); +#else +typedef HDEVINFO (WINAPI *SetupDiGetClassDevsPROCADDR)(CONST GUID *ClassGuid,PCSTR Enumerator,HWND hwndParent,DWORD Flags); +typedef WINBOOL (WINAPI *SetupDiGetDeviceInstanceIdPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,PSTR DeviceInstanceId,DWORD DeviceInstanceIdSize,PDWORD RequiredSize); +typedef WINBOOL (WINAPI *SetupDiGetDeviceInterfaceDetailPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,DWORD DeviceInterfaceDetailDataSize,PDWORD RequiredSize,PSP_DEVINFO_DATA DeviceInfoData); +#endif + +typedef WINBOOL (WINAPI *SetupDiEnumDeviceInfoPROCADDR)(HDEVINFO DeviceInfoSet,DWORD MemberIndex,PSP_DEVINFO_DATA DeviceInfoData); +typedef WINBOOL (WINAPI *SetupDiEnumDeviceInterfacesPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,CONST GUID *InterfaceClassGuid,DWORD MemberIndex,PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData); +typedef HKEY (WINAPI *SetupDiOpenDevRegKeyPROCADDR)(HDEVINFO DeviceInfoSet,PSP_DEVINFO_DATA DeviceInfoData,DWORD Scope,DWORD HwProfile,DWORD KeyType,REGSAM samDesired); +typedef WINBOOL (WINAPI *SetupDiDestroyDeviceInfoListPROCADDR)(HDEVINFO DeviceInfoSet); + +static int WinSetupAPI_avail = 0; +static SetupDiGetClassDevsPROCADDR WinSetup_SetupDiGetClassDevs = NULL; +static SetupDiGetDeviceInstanceIdPROCADDR WinSetup_SetupDiGetDeviceInstanceId = NULL; +static SetupDiGetDeviceInterfaceDetailPROCADDR WinSetup_SetupDiGetDeviceInterfaceDetail = NULL; +static SetupDiEnumDeviceInfoPROCADDR WinSetup_SetupDiEnumDeviceInfo = NULL; +static SetupDiEnumDeviceInterfacesPROCADDR WinSetup_SetupDiEnumDeviceInterfaces = NULL; +static SetupDiOpenDevRegKeyPROCADDR WinSetup_SetupDiOpenDevRegKey = NULL; +static SetupDiDestroyDeviceInfoListPROCADDR WinSetup_SetupDiDestroyDeviceInfoList = NULL; + +static int _init = 0; + +int NewtEDID_init() { + if( !_init ) { + WinSetupAPI_avail = 0; + HANDLE setup = LoadLibrary(TEXT("setupapi.dll")); + if( setup ) { + #ifdef _UNICODE + WinSetup_SetupDiGetClassDevs = (SetupDiGetClassDevsPROCADDR) GetProcAddressA(setup, "SetupDiGetClassDevsW"); + WinSetup_SetupDiGetDeviceInstanceId = (SetupDiGetDeviceInstanceIdPROCADDR) GetProcAddressA(setup, "SetupDiGetDeviceInstanceIdW"); + WinSetup_SetupDiGetDeviceInterfaceDetail = (SetupDiGetDeviceInterfaceDetailPROCADDR) GetProcAddressA(setup, "SetupDiGetDeviceInterfaceDetailW"); + #else + WinSetup_SetupDiGetClassDevs = (SetupDiGetClassDevsPROCADDR) GetProcAddressA(setup, "SetupDiGetClassDevsA"); + WinSetup_SetupDiGetDeviceInstanceId = (SetupDiGetDeviceInstanceIdPROCADDR) GetProcAddressA(setup, "SetupDiGetDeviceInstanceIdA"); + WinSetup_SetupDiGetDeviceInterfaceDetail = (SetupDiGetDeviceInterfaceDetailPROCADDR) GetProcAddressA(setup, "SetupDiGetDeviceInterfaceDetailA"); + #endif + WinSetup_SetupDiEnumDeviceInfo = (SetupDiEnumDeviceInfoPROCADDR) GetProcAddressA(setup, "SetupDiEnumDeviceInfo"); + WinSetup_SetupDiEnumDeviceInterfaces = (SetupDiEnumDeviceInterfacesPROCADDR) GetProcAddressA(setup, "SetupDiEnumDeviceInterfaces"); + WinSetup_SetupDiOpenDevRegKey = (SetupDiOpenDevRegKeyPROCADDR) GetProcAddressA(setup, "SetupDiOpenDevRegKey"); + WinSetup_SetupDiDestroyDeviceInfoList = (SetupDiDestroyDeviceInfoListPROCADDR) GetProcAddressA(setup, "SetupDiDestroyDeviceInfoList"); + if( NULL != WinSetup_SetupDiGetClassDevs && + NULL != WinSetup_SetupDiGetDeviceInstanceId && + NULL != WinSetup_SetupDiGetDeviceInterfaceDetail && + NULL != WinSetup_SetupDiEnumDeviceInfo && + NULL != WinSetup_SetupDiEnumDeviceInterfaces && + NULL != WinSetup_SetupDiOpenDevRegKey && + NULL != WinSetup_SetupDiDestroyDeviceInfoList ) { + WinSetupAPI_avail = 1; + } + } + _init = 1; + } + return WinSetupAPI_avail; +} + +static _TCHAR* Get2ndSlashBlock(const _TCHAR* sIn, _TCHAR* sOut, size_t sOutLen) +{ + _TCHAR* s = _tcschr(sIn, '\\'); + if( NULL != s ) { + s += 1; // skip '\\' + _TCHAR* t = _tcschr(s, '\\'); + if( NULL != t ) { + size_t len = t - s; + if( len > 0 ) { + if( sOutLen >= len ) { + _tcsncpy_s(sOut, sOutLen, s, len); + return sOut; + } + } + } + } + return NULL; +} + +static int GetMonitorSizeFromEDIDByRegKey(const HKEY hEDIDRegKey, int* widthMm, int* heightMm, int *widthCm, int *heightCm) +{ + DWORD dwType, actualValueNameLength = NAME_SIZE; + _TCHAR valueName[NAME_SIZE]; + + BYTE edidData[1024]; + DWORD edidSize = sizeof(edidData); + + *widthMm = -1; + *heightMm = -1; + *widthCm = -1; + *heightCm = -1; + + LONG retValue; + DWORD i; + for (i = 0, retValue = ERROR_SUCCESS; retValue != ERROR_NO_MORE_ITEMS; i++) { + retValue = RegEnumValue(hEDIDRegKey, i, &valueName[0], + &actualValueNameLength, NULL, &dwType, + edidData, // buffer + &edidSize); // buffer size + + if ( retValue == ERROR_SUCCESS && edidSize >= 23 && + 0 == _tcscmp(valueName, _T("EDID")) ) + { + DBG_PRINT("*** EDID Version %d.%d, data-size %d\n", (int)edidData[18], (int)edidData[19], edidSize); + if( edidSize >= 69 ) { + // 54 + 12 = 66: Horizontal display size, mm, 8 lsbits (0–4095 mm, 161 in) + // 54 + 13 = 67: Vertical display size, mm, 8 lsbits (0–4095 mm, 161 in) + // 54 + 14 = 68: + // Bits 7–4 Horizontal display size, mm, 4 msbits + // Bits 3–0 Vertical display size, mm, 4 msbits + *widthMm = ( (int)(edidData[68] & 0xF0) << 4 ) | (int)edidData[66]; + *heightMm = ( (int)(edidData[68] & 0x0F) << 8 ) | (int)edidData[67]; + } + *widthCm = (int) edidData[21]; + *heightCm = (int) edidData[22]; + return 1; // valid EDID found + } + } + return 0; // EDID not found +} + +int NewtEDID_GetMonitorSizeFromEDIDByModelName(const DISPLAY_DEVICE* ddMon, int* widthMm, int* heightMm, int *widthCm, int *heightCm) +{ + _TCHAR useDevModelNameStore[MAX_DEVICE_ID_LEN]; + _TCHAR *useDevModelName = Get2ndSlashBlock(ddMon->DeviceID, useDevModelNameStore, MAX_DEVICE_ID_LEN); + if( NULL == useDevModelName ) { + return 0; + } + + HDEVINFO devInfo = WinSetup_SetupDiGetClassDevs( + &GUID_CLASS_MONITOR, //class GUID + NULL, //enumerator + NULL, //HWND + DIGCF_PRESENT | DIGCF_PROFILE); // Flags //DIGCF_ALLCLASSES| + + if (NULL == devInfo) { + return 0; + } + + int bRes = 0; + DWORD i; + DWORD lastError = ERROR_SUCCESS; + for (i = 0; !bRes && ERROR_SUCCESS == lastError; i++) { + SP_DEVINFO_DATA devInfoData; + memset(&devInfoData, 0, sizeof(devInfoData)); + devInfoData.cbSize = sizeof(devInfoData); + + if (WinSetup_SetupDiEnumDeviceInfo(devInfo, i, &devInfoData)) { + _TCHAR devModelName[MAX_DEVICE_ID_LEN]; + WinSetup_SetupDiGetDeviceInstanceId(devInfo, &devInfoData, devModelName, MAX_PATH, NULL); + + if( NULL != _tcsstr(devModelName, useDevModelName) ) { + HKEY hEDIDRegKey = WinSetup_SetupDiOpenDevRegKey(devInfo, &devInfoData, + DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + + if ( 0 != hEDIDRegKey && hEDIDRegKey != INVALID_HANDLE_VALUE ) { + bRes = GetMonitorSizeFromEDIDByRegKey(hEDIDRegKey, widthMm, heightMm, widthCm, heightCm); + RegCloseKey(hEDIDRegKey); + } + } + } + lastError = GetLastError(); + } + WinSetup_SetupDiDestroyDeviceInfoList(devInfo); + return bRes; +} + +int NewtEDID_GetMonitorSizeFromEDIDByDevice(const DISPLAY_DEVICE* ddMon, int* widthMm, int* heightMm, int *widthCm, int *heightCm) +{ + HDEVINFO devInfo = WinSetup_SetupDiGetClassDevs( + &GUID_DEVINTERFACE_MONITOR, + NULL, //enumerator + NULL, //HWND + DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); // Flags //DIGCF_ALLCLASSES| + + if (NULL == devInfo) { + return 0; + } + + DWORD devIfaceDetailDataSize = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA, DevicePath) + MAX_PATH * sizeof(TCHAR); + PSP_DEVICE_INTERFACE_DETAIL_DATA pDevIfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(devIfaceDetailDataSize); + + int bRes = 0; + DWORD i; + DWORD lastError = ERROR_SUCCESS; + for (i = 0; !bRes && ERROR_SUCCESS == lastError; i++) { + SP_DEVICE_INTERFACE_DATA devIfaceData; + memset(&devIfaceData, 0, sizeof(devIfaceData)); + devIfaceData.cbSize = sizeof(devIfaceData); + + if ( WinSetup_SetupDiEnumDeviceInterfaces(devInfo, NULL, &GUID_DEVINTERFACE_MONITOR, i, &devIfaceData) ) { + memset(pDevIfaceDetailData, 0, devIfaceDetailDataSize); + pDevIfaceDetailData->cbSize = sizeof(*pDevIfaceDetailData); + DWORD devIfaceDetailDataReqSize = 0; + SP_DEVINFO_DATA devInfoData2; + memset(&devInfoData2, 0, sizeof(devInfoData2)); + devInfoData2.cbSize = sizeof(devInfoData2); + if( WinSetup_SetupDiGetDeviceInterfaceDetail(devInfo, &devIfaceData, pDevIfaceDetailData, devIfaceDetailDataSize, + &devIfaceDetailDataReqSize, &devInfoData2) ) { + int found = 0 == _tcsicmp(pDevIfaceDetailData->DevicePath, ddMon->DeviceID); + DBG_PRINT("*** Got[%d].2 found %d, devicePath <%s>\n", i, found, pDevIfaceDetailData->DevicePath); + if( found ) { + HKEY hEDIDRegKey = WinSetup_SetupDiOpenDevRegKey(devInfo, &devInfoData2, + DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); + DBG_PRINT("*** Got[%d] hEDIDRegKey %p\n", i, (void*)hEDIDRegKey); + if ( 0 != hEDIDRegKey && hEDIDRegKey != INVALID_HANDLE_VALUE ) { + bRes = GetMonitorSizeFromEDIDByRegKey(hEDIDRegKey, widthMm, heightMm, widthCm, heightCm); + RegCloseKey(hEDIDRegKey); + } + } + } else { + lastError = GetLastError(); + DBG_PRINT("*** fail.2 at %d, werr %d\n", i, lastError); + } + } else { + lastError = GetLastError(); + DBG_PRINT("*** fail.1 at %d, werr %d\n", i, lastError); + } + } + DBG_PRINT("*** Result: found %d, enum-iter %d, werr %d\n", bRes, i, (int)lastError); + WinSetup_SetupDiDestroyDeviceInfoList(devInfo); + free(pDevIfaceDetailData); + return bRes; +} + +int NewtEDID_GetIndexedDisplayDevice(int useDevIdx, int useMonIdx, DISPLAY_DEVICE* ddMonOut, int getDeviceInterfaceName, int verbose) +{ + DISPLAY_DEVICE ddAdp; + DWORD devIdx; // device index + DWORD monIdx; // monitor index + + memset(&ddAdp, 0, sizeof(ddAdp)); + ddAdp.cb = sizeof(ddAdp); + + const DWORD dwFlagsMonitor = 0 != getDeviceInterfaceName ? EDD_GET_DEVICE_INTERFACE_NAME : 0; + + for(devIdx = 0; + ( devIdx <= useDevIdx || 0 > useDevIdx ) && EnumDisplayDevices(0, devIdx, &ddAdp, 0); + devIdx++) + { + if( NULL != ddAdp.DeviceName && 0 != _tcslen(ddAdp.DeviceName) ) { + if( verbose ) { + _ftprintf(stderr, __T("*** [%02d:__]: deviceName <%s> flags 0x%X active %d\n"), + devIdx, ddAdp.DeviceName, ddAdp.StateFlags, ( 0 != ( ddAdp.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) ); + _ftprintf(stderr, __T(" deviceString <%s> \n"), ddAdp.DeviceString); + _ftprintf(stderr, __T(" deviceID <%s> \n"), ddAdp.DeviceID); + } + if( devIdx == useDevIdx || 0 > useDevIdx ) { + DISPLAY_DEVICE ddMon; + memset(&ddMon, 0, sizeof(ddMon)); + ddMon.cb = sizeof(ddMon); + + for(monIdx = 0; + ( monIdx <= useMonIdx || 0 > useMonIdx ) && EnumDisplayDevices(ddAdp.DeviceName, monIdx, &ddMon, dwFlagsMonitor); + monIdx++) + { + if( NULL != ddMon.DeviceName && 0 < _tcslen(ddMon.DeviceName) ) { + if( verbose ) { + _ftprintf(stderr, __T("*** [%02d:%02d]: deviceName <%s> flags 0x%X active %d\n"), + devIdx, monIdx, ddMon.DeviceName, ddMon.StateFlags, ( 0 != ( ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE ) ) ); + _ftprintf(stderr, __T(" deviceString <%s> \n"), ddMon.DeviceString); + _ftprintf(stderr, __T(" deviceID <%s> \n"), ddMon.DeviceID); + } + if( monIdx == useMonIdx ) { + *ddMonOut = ddMon; + return 1; + } + } + memset(&ddMon, 0, sizeof(ddMon)); + ddMon.cb = sizeof(ddMon); + } + } + } + memset(&ddAdp, 0, sizeof(ddAdp)); + ddAdp.cb = sizeof(ddAdp); + } + memset(ddMonOut, 0, sizeof(*ddMonOut)); + ddMonOut->cb = sizeof(*ddMonOut); + return 0; +} + +#ifdef WINDOWS_EDID_WITH_MAIN + +int _tmain(int argc, _TCHAR* argv []) +{ +#ifdef _UNICODE + _ftprintf(stderr, __T("_UNICODE enabled\n")); +#else + fprintf(stderr, "_UNICODE disabled\n"); +#endif + if( !NewtEDID_init() ) { + _ftprintf(stderr, __T("setupapi not available\n")); + return 1; + } + DISPLAY_DEVICE ddMon; + + if( 3 != argc ) { + NewtEDID_GetIndexedDisplayDevice(-1, -1, &ddMon, 0 /* getDeviceInterfaceName */, 1 /* verbose */); + _ftprintf(stderr, __T("Usage: %s dev-idx mon-idx\n"), argv[0]); + return 1; + } + int useDevIdx = _tstoi(argv[1]); + int useMonIdx = _tstoi(argv[2]); + int widthMm, heightMm; + int widthCm, heightCm; + + // + // Proper method + // + if( 0 == NewtEDID_GetIndexedDisplayDevice(useDevIdx, useMonIdx, &ddMon, 1 /* getDeviceInterfaceName */, 0 /* verbose */) ) { + _ftprintf(stderr, __T("No monitor found at dev %d : mon %d\n"), useDevIdx, useMonIdx); + return 1; + } + _ftprintf(stderr, __T("Found monitor at dev %d : mon %d:\n"), useDevIdx, useMonIdx); + _ftprintf(stderr, __T(" Device Name : %s\n"), ddMon.DeviceName); + _ftprintf(stderr, __T(" Device String: %s\n"), ddMon.DeviceString); + _ftprintf(stderr, __T(" Device ID : %s\n"), ddMon.DeviceID); + fflush(NULL); + + if( NewtEDID_GetMonitorSizeFromEDIDByDevice(&ddMon, &widthMm, &heightMm, &widthCm, &heightCm) ) { + _ftprintf(stderr, __T("Proper: Found EDID size [%d, %d] [mm], [%d, %d] [cm]\n"), widthMm, heightMm, widthCm, heightCm); + } + + // + // Monitor model name method + // + if( 0 == NewtEDID_GetIndexedDisplayDevice(useDevIdx, useMonIdx, &ddMon, 0 /* getDeviceInterfaceName */, 0 /* verbose */) ) { + _ftprintf(stderr, __T("No monitor found at dev %d : mon %d\n"), useDevIdx, useMonIdx); + return 1; + } + _ftprintf(stderr, __T("Found monitor at dev %d : mon %d:\n"), useDevIdx, useMonIdx); + _ftprintf(stderr, __T(" Device Name : %s\n"), ddMon.DeviceName); + _ftprintf(stderr, __T(" Device String: %s\n"), ddMon.DeviceString); + _ftprintf(stderr, __T(" Device ID : %s\n"), ddMon.DeviceID); + fflush(NULL); + + if( NewtEDID_GetMonitorSizeFromEDIDByModelName(&ddMon, &widthMm, &heightMm, &widthCm, &heightCm) ) { + _ftprintf(stderr, __T("ModelN: Found EDID size [%d, %d] [mm], [%d, %d] [cm]\n"), widthMm, heightMm, widthCm, heightCm); + } + return 0; +} + +#endif /* WINDOWS_EDID_WITH_MAIN */ |