__declspec(dllexport) void  GetCurrentTopology(DISPLAYCONFIG_TOPOLOGY_ID *peCurrentTopology) {

      // Get the current topology - make sure that we aren't resetting the topology to the same that it
      // currently is - otherwise it can cause unnecessary flashing on the screen.
      LONG result;
      UINT32 NumPathArrayElements;
      UINT32 NumModeInfoArrayElements;
      DISPLAYCONFIG_PATH_INFO *pPathInfoArray;
      DISPLAYCONFIG_MODE_INFO *pModeInfoArray;
      result = GetDisplayConfigBufferSizes(QDC_DATABASE_CURRENT, &NumPathArrayElements, &NumModeInfoArrayElements);

      if (result != ERROR_SUCCESS)
            return;

      if (peCurrentTopology == NULL)
            return;

      // The only reason to allocate these structures is that the documentation says that QueryDisplayConfig
      // cannot take null for the pPathInfoArray and pModeInfoArray  elements.  I have tried to have static
      // structures that get passed in with only one element and have had things fail in the past
      // The only way that I've gotten this interface to reliably work is to call GetDisplayConfigBufferSizes
      // and then allocate AND ZERO the structures that are passed in.  This interface is incredibly
      // fragile and you are going to want to do everything that it expects, or it will return
      // "invalid parameter"
      pPathInfoArray = (DISPLAYCONFIG_PATH_INFO *)malloc(NumPathArrayElements * sizeof(DISPLAYCONFIG_PATH_INFO));
      if (!pPathInfoArray)
            return;
      pModeInfoArray = (DISPLAYCONFIG_MODE_INFO *)malloc(NumModeInfoArrayElements * sizeof(DISPLAYCONFIG_MODE_INFO));
      if (!pModeInfoArray)
      {
            if (pPathInfoArray)
                  free(pPathInfoArray);
            return;
      }
      memset(pPathInfoArray, 0, NumPathArrayElements * sizeof(DISPLAYCONFIG_PATH_INFO));
      memset(pModeInfoArray, 0, NumModeInfoArrayElements * sizeof(DISPLAYCONFIG_MODE_INFO));

      result = QueryDisplayConfig(QDC_DATABASE_CURRENT,
                                                &NumPathArrayElements,
                                                pPathInfoArray,
                                                &NumModeInfoArrayElements,
                                                pModeInfoArray,
                                                peCurrentTopology);

      // Free the structures, don't care what is in them
      free(pPathInfoArray);
      free(pModeInfoArray);
      if (result != ERROR_SUCCESS)
            return;
      return;
}
int getCurrentSettings(UINT32* num_of_paths, UINT32* num_of_modes, DISPLAYCONFIG_PATH_INFO** displayPaths, DISPLAYCONFIG_MODE_INFO** displayModes) {
    // Get number of paths, and number of modes in query
    if (!Result_DCGDI(GetDisplayConfigBufferSizes(QDC_ALL_PATHS, num_of_paths, num_of_modes)))
        return 0;
    
    // Allocate paths and modes dynamically
    *displayPaths = (DISPLAYCONFIG_PATH_INFO*)calloc((int)num_of_paths, sizeof(DISPLAYCONFIG_PATH_INFO));
    *displayModes = (DISPLAYCONFIG_MODE_INFO*)calloc((int)num_of_modes, sizeof(DISPLAYCONFIG_MODE_INFO));
    
    // Query for the information (fill in the arrays above)
    if (!Result_QDC(QueryDisplayConfig(QDC_ALL_PATHS, num_of_paths, (*displayPaths), num_of_modes, (*displayModes), NULL)))
        return 0;
    
    return 1;
}
// Get current refresh rate on Win7
double W7GetRefreshRate(int monitorIdx)
{
  UINT32 uNumPathArrayElements = 0;
  UINT32 uNumModeInfoArrayElements = 0;
  DISPLAYCONFIG_PATH_INFO* pPathInfoArray = NULL;
  DISPLAYCONFIG_MODE_INFO* pModeInfoArray = NULL;
  DISPLAYCONFIG_TOPOLOGY_ID* pCurrentTopologyId = NULL;
  LONG result;
  double refreshRate = -1;
  DISPLAY_DEVICE displayDevice;
  displayDevice.cb = sizeof(DISPLAY_DEVICE);
  DEVMODE devMode;
  devMode.dmSize = sizeof(DEVMODE);
  DEVMODE *paDeviceMode;

  if(EnumDisplayDevices(NULL, monitorIdx, &displayDevice, 0))
  {
    EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode);
  }
  paDeviceMode = &devMode;

  // Get size of buffers for QueryDisplayConfig
  result = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &uNumPathArrayElements, &uNumModeInfoArrayElements);
  if (result != 0)
  {
    return(refreshRate);
  }

  // allocate memory for QueryDisplayConfig buffers
  pPathInfoArray = (DISPLAYCONFIG_PATH_INFO*)calloc(uNumPathArrayElements, sizeof(DISPLAYCONFIG_PATH_INFO));
  if (pPathInfoArray == NULL)
  {
    return(refreshRate);
  }

  pModeInfoArray = (DISPLAYCONFIG_MODE_INFO*)calloc(uNumModeInfoArrayElements, sizeof(DISPLAYCONFIG_MODE_INFO));
  if (pModeInfoArray == NULL)
  {
    // freeing memory
    free(pPathInfoArray);
    return(refreshRate);
  }

  // get display configuration
  result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, 
                              &uNumPathArrayElements, pPathInfoArray, 
                              &uNumModeInfoArrayElements, pModeInfoArray,
                              pCurrentTopologyId);
  if (result == 0)
  {
    //// Get information from active target path and based on current dimension (support for multiple displays)
    for (UINT i = 0; i < uNumPathArrayElements; ++i)
    {
      UINT iModIdx = pPathInfoArray[i].sourceInfo.modeInfoIdx;
      if(pPathInfoArray[i].flags == DISPLAYCONFIG_PATH_ACTIVE && paDeviceMode[0].dmPosition.x == pModeInfoArray[iModIdx].sourceMode.position.x && paDeviceMode[0].dmPosition.y == pModeInfoArray[iModIdx].sourceMode.position.y)
      {
        if(paDeviceMode[0].dmPelsHeight == pModeInfoArray[iModIdx].sourceMode.height && paDeviceMode[0].dmPelsWidth == pModeInfoArray[iModIdx].sourceMode.width)
        {
          monitorIdx = i;
          DISPLAYCONFIG_PATH_TARGET_INFO target;
          target = pPathInfoArray[monitorIdx].targetInfo;
          LONG numerator = target.refreshRate.Numerator;
          LONG denominator = target.refreshRate.Denominator;
          refreshRate = (double)numerator/(double)denominator;
          break;
        }
      }
    }
  }
  // freeing memory
  free(pPathInfoArray);
  free(pModeInfoArray);

  return(refreshRate);
}