Win32 code to get EDID in Windows XP/7

拈花ヽ惹草 提交于 2019-11-27 19:12:40

问题


I found this page and was unable to get any useful information out of it (it searches the registry for something but never finds it and goes into an infinite loop).

As this question regarding getting the monitor serial UID ("EDID information") asks I would like the same information but from the point of view of Win32 C code (or C/C++ DDK code, or whatever) instead of Linux.


回答1:


WMI didn't support monitor classes in Windows XP. The documented way of getting the EDID was - and still is - with the Setup API.

Longer survey and a VC++ code sample are available here.




回答2:


First I got a C# version working using WMI Code Creator:

        try
        {
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher("root\\WMI",
                "SELECT * FROM WmiMonitorID");

            foreach (ManagementObject queryObj in searcher.Get())
            {
                Console.WriteLine("-----------------------------------");
                Console.WriteLine("WmiMonitorID instance");
                Console.WriteLine("-----------------------------------");
                //Console.WriteLine("Active: {0}", queryObj["Active"]);
                Console.WriteLine("InstanceName: {0}", queryObj["InstanceName"]);
                dynamic snid = queryObj["SerialNumberID"];

                Console.WriteLine("SerialNumberID: (length) {0}", snid.Length);
                Console.WriteLine("YearOfManufacture: {0}", queryObj["YearOfManufacture"]);
                dynamic code = queryObj["ProductCodeID"];
                string pcid = "";
                for (int i = 0; i < code.Length; i++)
                {
                    pcid = pcid + Char.ConvertFromUtf32(code[i]);
                    //pcid = pcid +code[i].ToString("X4");
                }
                Console.WriteLine("ProductCodeID: " +  pcid);
            }
        }
        catch (ManagementException e)
        {
            Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
        }

Below is the C++ code I found and tweaked to work with the InstanceName field in WmiMonitorID class (EDID structure) that I wanted to read. Don't forget to add setupapi.lib to your Linker > Additional Libraries build setting.

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")

int EnumMonitorIDs()
{
    ret.clear();

    HRESULT hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
            << hex << hres << endl;
        return 1;                  // Program has failed.
    }

    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
            << hex << hres << endl;
        CoUninitialize();
        return 1;
    }

    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);

    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

    IWbemServices *pSvc = NULL; 
    BSTR AbackB = SysAllocString(L"root\\WMI");
    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         AbackB, // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (e.g. Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );
    SysFreeString(AbackB);

    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
             << hex << hres << endl;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

    hres = CoSetProxyBlanket(
       pSvc,                        // Indicates the proxy to set
       RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
       RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
       NULL,                        // Server principal name 
       RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
       RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
       NULL,                        // client identity
       EOAC_NONE                    // proxy capabilities 
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

    BSTR wql = SysAllocString(L"WQL");
    BSTR select = SysAllocString(L"SELECT * FROM WmiMonitorID");
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        wql,
        select,
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
        NULL,
        &pEnumerator);
    SysFreeString(wql);
    SysFreeString(select);

    if (FAILED(hres))
    {
        cout << "Query for operating system name failed."
            << " Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

    IWbemClassObject *pclsObj = 0;
    ULONG uReturn = 0;   
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if (0 == uReturn)
        {
            break;
        }

        // ok, we have the EDID record, pull some fields out of it

        VARIANT vtProp;
        hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0);
        wcout << "----------------" << endl << "InstanceName : " << vtProp.bstrVal << endl;
        VariantClear(&vtProp);



        pclsObj->Release();
    }

    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();

    return 0;
}



回答3:


Based on Ofek Shilon's blog post, and tweaked to get all the device IDs (manufacturer ID + product ID strings):

DISPLAY_DEVICE dd;
dd.cb = sizeof(dd);
DWORD dev = 0;  // device index
int id = 1;        // monitor number, as used by Display Properties > Settings

Str DeviceID;

while (EnumDisplayDevices(0, dev, &dd, 0))
{
    DISPLAY_DEVICE ddMon;
    ZeroMemory(&ddMon, sizeof(ddMon));
    ddMon.cb = sizeof(ddMon);
    DWORD devMon = 0;

    while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0))
    {
        DeviceID.Sprintf("%s", ddMon.DeviceID);
        DeviceID = DeviceID.Slice(8);
        if (DeviceID.Index("\\") > 0)
            DeviceID = DeviceID.Slice(0, DeviceID.Index("\\"));

        printf ("DEVICEID = %s --------\n", DeviceID.utf8());
    }

    devMon++;

    ZeroMemory(&ddMon, sizeof(ddMon));
    ddMon.cb = sizeof(ddMon);
  }

  ZeroMemory(&dd, sizeof(dd));
  dd.cb = sizeof(dd);
  dev++;
}

N.B. Str here is a custom string class but should be easy to refactor to use anything.



来源:https://stackoverflow.com/questions/6363699/win32-code-to-get-edid-in-windows-xp-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!