title: I2C error when using the Windows Monitor Configuration Functions
body: <p>I'm attempting to get/set the brightness level of the monitor through the Windows API. I've tried both the <a href="https://msdn.microsoft.com/en-us/library/dd692982(v=vs.85).aspx" rel="noreferrer">Low-Level Monitor Configuration Functions</a> and the <a href="https://msdn.microsoft.com/en-us/library/dd692981(v=vs.85).aspx" rel="noreferrer">High-Level Monitor Configuration Functions</a>, but they both seem to be breaking in the same place. In both cases I have no problem getting the HMONITOR handle and getting the physical monitor handle from the HMONITOR, but once I try to query the DDC/CI capabilities, I get an error saying "<code>An error occurred while transmitting data to the device on the I2C bus.</code>"</p>
  
  <p>The particular functions that cause this error are <a href="https://msdn.microsoft.com/en-us/library/dd692940(v=vs.85).aspx" rel="noreferrer">GetMonitorCapabilities</a> for the high-level functions and <a href="https://msdn.microsoft.com/en-us/library/dd692938(v=vs.85).aspx" rel="noreferrer">GetCapabilitiesStringLength</a> for the low-level functions. They both cause the same error.</p>
  
  <p>This leads me to believe that maybe my monitor doesn't support DDC/CI, but I know my laptop's monitor brightness can be changed through the control panel, so it must be controlled through software somehow. Also I can successfully use the WMI classes in a PowerShell script to get/set the brightness as described on <a href="http://blogs.technet.com/b/heyscriptingguy/archive/2013/07/25/use-powershell-to-report-and-set-monitor-brightness.aspx" rel="noreferrer">this</a> page. Most things I've read suggest that most modern laptop screens do support DDC/CI.</p>
  
  <p>Is there any way to find out what is causing this error or to get more information about it? I'm currently working in C++ in Visual Studio 2013 on Windows 7. I could probably use WMI in my C++ program if I can't get this current method working, but I thought I would ask here first.</p>
  
  <p>Here's the code I currently have:</p>
  
  <pre><code>#include "stdafx.h"
  #include &lt;windows.h&gt;
  #include &lt;highlevelmonitorconfigurationapi.h&gt;
  #include &lt;lowlevelmonitorconfigurationapi.h&gt;
  #include &lt;physicalmonitorenumerationapi.h&gt;
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  
  int _tmain(int argc, _TCHAR* argv[])
  {
    DWORD minBrightness, curBrightness, maxBrightness;
    HWND curWin = GetConsoleWindow();
    if (curWin == NULL) {
      std::cout &lt;&lt; "Problem getting a handle to the window." &lt;&lt; std::endl;
      return 1;
    }
  
    // Call MonitorFromWindow to get the HMONITOR handle
    HMONITOR curMon = MonitorFromWindow(curWin, MONITOR_DEFAULTTONULL);
    if (curMon == NULL) {
      std::cout &lt;&lt; "Problem getting the display monitor" &lt;&lt; std::endl;
      return 1;
    }
  
    // Call GetNumberOfPhysicalMonitorsFromHMONITOR to get the needed array size
    DWORD monitorCount;
    if (!GetNumberOfPhysicalMonitorsFromHMONITOR(curMon, &amp;monitorCount)) {
      std::cout &lt;&lt; "Problem getting the number of physical monitors" &lt;&lt; std::endl;
      return 1;
    }
  
    // Call GetPhysicalMonitorsFromHMONITOR to get a handle to the physical monitor 
    LPPHYSICAL_MONITOR physicalMonitors = (LPPHYSICAL_MONITOR)malloc(monitorCount*sizeof(PHYSICAL_MONITOR));
    if (physicalMonitors == NULL) {
      std::cout &lt;&lt; "Unable to malloc the physical monitor array." &lt;&lt; std::endl;
      return 1;
    }
    if (!GetPhysicalMonitorsFromHMONITOR(curMon, monitorCount, physicalMonitors)) {
      std::cout &lt;&lt; "Problem getting the physical monitors." &lt;&lt; std::endl;
      return 1;
    }
  
    std::cout &lt;&lt; "Num Monitors: " &lt;&lt; monitorCount &lt;&lt; std::endl;   // This prints '1' as expected.
    wprintf(L"%s\n", physicalMonitors[0].szPhysicalMonitorDescription);  // This prints "Generic PnP Monitor" as expected
  
    // Call GetMonitorCapabilities to find out which functions it supports
    DWORD monCaps;
    DWORD monColorTemps;
    // The following function call fails with the error "An error occurred while transmitting data to the device on the I2C bus."
    if (!GetMonitorCapabilities(physicalMonitors[0].hPhysicalMonitor, &amp;monCaps, &amp;monColorTemps)) {
      std::cout &lt;&lt; "Problem getting the monitor's capabilities." &lt;&lt; std::endl;
      DWORD errNum = GetLastError();
      DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
      LPVOID buffer;
      FormatMessage(flags, NULL, errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&amp;buffer, 0, NULL);
      wprintf(L"%s\n", buffer);
      return 1;
    }
    // Same error when I use GetCapabilitiesStringLength(...) here.
  
    // More code that is currently never reached...
  
      return 0;
  }
  </code></pre>
  
  <p>Edit: Also I should note that <code>physicalMonitors[0].hPhysicalMonitor</code> is 0, even though the monitor count and text description are valid and the <code>GetPhysicalMonitorsFromHMONITOR</code> function returns successfully. Any thoughts on why this might be?</p>