0

Using the same methods as in answers to other questions related to getting display names through WinApi (using EnumDisplayDevicesW while passing the device name as the first parameter, similarly to e.g. this one), I've been able to achieve partial success. The issue I'm having is that I'm getting incomplete information. The "Advanced display settings" panel which can be accessed by right clicking on the desktop, selecting "Display settings", and then selecting "Advanced display settings" on the bottom displays the following displays:

DELL P2414H(DisplayPort)
AOC AG271QG
BenQ PJ

However, through the use of EnumDisplayDevicesW calls, I extracted the following:

AOC AG271QG
DELL P2414H(DisplayPort)
Generic PnP Monitor

While the order doesn't matter to me, the issue is that I'm getting "Generic PnP Monitor" rather than the more helpful "BenQ PJ" (which is not the exact model that I was hoping for, but still provides at least some information). What can I do to extract "BenQ PJ" rather than "Generic PnP Monitor" (preferably remaining within WinApi)?

Community
  • 1
  • 1
Noctiphobia
  • 757
  • 1
  • 8
  • 27
  • Looks like you need nested calls see: https://docs.microsoft.com/en-us/windows/desktop/gdi/getting-information-on-a-display-monitor – Richard Critten Jul 02 '19 at 00:50
  • The nested calls is what I already use (they're also implemented in the question I linked) - without them, I wouldn't get information on the other monitors (and instead just on the adapter, so the GPU). I'm sure that this API call won't get me any further. In fact, the same "Generic PnP Monitor" pops up when I click "Display adapter properties for Display 3" in the window I mentioned - so there are certainly 2 sources of different information (and `EnumDisplayDevicesW` apparently isn't the one I'm looking for). – Noctiphobia Jul 02 '19 at 02:21
  • Have you looked through the long combobox of device properties in the properties dialog of the monitor in Device Manager to see if the string you want appears somewhere there? – Ben Voigt Jul 02 '19 at 03:55
  • The screen's have no driver installed and therefore the actual device itself is running with the Generic PnP Monitor Driver. I think you'd better check it. Look in Device Manager and you will see. – Drake Wu Jul 02 '19 at 06:47

1 Answers1

2

You can get Monitor information with EDID

EDID can be read with WMI

For example, test with WmiOpenBlock and so on, to reduce code of WMI in C++ =>

I get for my monitor :

Instance Name = DISPLAY\PHLC085\4&20634529&0&UID65793_0
User Friendly Name = 247ELH
Manufacturer Name = PHL
Product Code ID = C085
Serial Number ID = AU01307001613

Includes and defines =>

#define _CRT_NON_CONFORMING_SWPRINTFS
#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <tchar.h>
#include <initguid.h>
#include <wmistr.h>
DEFINE_GUID(WmiMonitorID_GUID, 0x671a8285, 0x4edb, 0x4cae, 0x99,0xfe,0x69,0xa1,0x5c,0x48,0xc0,0xbc );
typedef struct WmiMonitorID {
    USHORT ProductCodeID[16];
    USHORT SerialNumberID[16];
    USHORT ManufacturerName[16];
    UCHAR WeekOfManufacture;
    USHORT YearOfManufacture;
    USHORT UserFriendlyNameLength;
    USHORT UserFriendlyName[1];
} WmiMonitorID, *PWmiMonitorID;
#define OFFSET_TO_PTR(Base, Offset) ((PBYTE)((PBYTE)Base + Offset))

typedef HRESULT(WINAPI*WOB) (IN LPGUID lpGUID, IN DWORD nAccess, OUT LONG*);
WOB WmiOpenBlock;
typedef HRESULT(WINAPI*WQAD) (IN LONG hWMIHandle, ULONG* nBufferSize, OUT UCHAR * pBuffer);
WQAD WmiQueryAllData;
typedef HRESULT(WINAPI*WCB) (IN LONG);
WCB WmiCloseBlock;

Test code =>

HRESULT hr = E_FAIL;
LONG hWmiHandle;
PWmiMonitorID MonitorID;
HINSTANCE hDLL = LoadLibrary(L"Advapi32.dll");
WmiOpenBlock = (WOB)GetProcAddress(hDLL, "WmiOpenBlock");
WmiQueryAllData = (WQAD)GetProcAddress(hDLL, "WmiQueryAllDataW");
WmiCloseBlock = (WCB)GetProcAddress(hDLL, "WmiCloseBlock");
if (WmiOpenBlock != NULL && WmiQueryAllData && WmiCloseBlock)
{
    WCHAR pszDeviceId[256] = L"";
    hr = WmiOpenBlock((LPGUID)&WmiMonitorID_GUID, GENERIC_READ, &hWmiHandle);
    if (hr == ERROR_SUCCESS)
    {
        ULONG nBufferSize = 0;
        UCHAR *pAllDataBuffer = 0;
        PWNODE_ALL_DATA pWmiAllData;
        hr = WmiQueryAllData(hWmiHandle, &nBufferSize, 0);
        if (hr == ERROR_INSUFFICIENT_BUFFER)
        {
            pAllDataBuffer = (UCHAR*)malloc(nBufferSize);
            hr = WmiQueryAllData(hWmiHandle, &nBufferSize, pAllDataBuffer);
            if (hr == ERROR_SUCCESS)
            {
                while (1)
                {
                    pWmiAllData = (PWNODE_ALL_DATA)pAllDataBuffer;
                    if (pWmiAllData->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE)
                        MonitorID = (PWmiMonitorID)&pAllDataBuffer[pWmiAllData->DataBlockOffset];
                    else
                        MonitorID = (PWmiMonitorID)&pAllDataBuffer[pWmiAllData->OffsetInstanceDataAndLength[0].OffsetInstanceData];

                    ULONG nOffset = 0;
                    WCHAR *pwsInstanceName = 0;
                    nOffset = (ULONG)pAllDataBuffer[pWmiAllData->OffsetInstanceNameOffsets];
                    pwsInstanceName = (WCHAR*)OFFSET_TO_PTR(pWmiAllData, nOffset + sizeof(USHORT));
                    WCHAR wsText[255] = L"";
                    swprintf(wsText, L"Instance Name = %s\r\n", pwsInstanceName);
                    OutputDebugString(wsText);

                    WCHAR *pwsUserFriendlyName;
                    pwsUserFriendlyName = (WCHAR*)MonitorID->UserFriendlyName;
                    swprintf(wsText, L"User Friendly Name = %s\r\n", pwsUserFriendlyName);
                    OutputDebugString(wsText);

                    WCHAR *pwsManufacturerName;
                    pwsManufacturerName = (WCHAR*)MonitorID->ManufacturerName;
                    swprintf(wsText, L"Manufacturer Name = %s\r\n", pwsManufacturerName);
                    OutputDebugString(wsText);

                    WCHAR *pwsProductCodeID;
                    pwsProductCodeID = (WCHAR*)MonitorID->ProductCodeID;
                    swprintf(wsText, L"Product Code ID = %s\r\n", pwsProductCodeID);
                    OutputDebugString(wsText);

                    WCHAR *pwsSerialNumberID;
                    pwsSerialNumberID = (WCHAR*)MonitorID->SerialNumberID;
                    swprintf(wsText, L"Serial Number ID = %s\r\n", pwsSerialNumberID);
                    OutputDebugString(wsText);

                    if (!pWmiAllData->WnodeHeader.Linkage)
                        break;
                    pAllDataBuffer += pWmiAllData->WnodeHeader.Linkage;
                }
                free(pAllDataBuffer);
            }
        }
        WmiCloseBlock(hWmiHandle);
    }
}
Castorix
  • 1,384
  • 1
  • 8
  • 10