summaryrefslogtreecommitdiffstats
path: root/src/newt/native/WindowsEDID.c
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2015-02-16 06:23:43 +0100
committerSven Gothel <[email protected]>2015-02-16 06:23:43 +0100
commit70faf070f50ea66fd4cc8f5f586614810f378787 (patch)
treec4e1175587337386620c823927c017c6fd68c727 /src/newt/native/WindowsEDID.c
parent1eea4278f1be5900f0d990d0a7d352923def217c (diff)
Bug 1129 - NEWT MonitorDevice's physical size on Windows must be read via EDID
On Windows, one must read the monitor's EDID data as stored in the registry, no 'simple' API works otherwise. The proper way requires utilizing the Windows Setup-API. 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.
Diffstat (limited to 'src/newt/native/WindowsEDID.c')
-rw-r--r--src/newt/native/WindowsEDID.c419
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 */