mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Brightness (Windows): uses COM-less method to query WMI
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+1
-1
@@ -1041,7 +1041,7 @@ elseif(WIN32)
|
||||
src/detection/bluetoothradio/bluetoothradio_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_windows.c
|
||||
src/detection/brightness/brightness_windows.cpp
|
||||
src/detection/brightness/brightness_windows.c
|
||||
src/detection/btrfs/btrfs_nosupport.c
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <windef.h>
|
||||
#include <wmistr.h>
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* The WmiOpenBlock function opens the WMI data block object for the specified WMI class.
|
||||
*
|
||||
* \param Guid Specifies the GUID for WMI class.
|
||||
* \param DesiredAccess Specifies the desired access rights to the data block object.
|
||||
* \param DataBlockHandle Pointer to a memory location where the routine returns a handle to the data block object.
|
||||
* \return ULONG Successful or errant status.
|
||||
*/
|
||||
NTSYSAPI ULONG NTAPI
|
||||
WmiOpenBlock(
|
||||
_In_ LPCGUID Guid,
|
||||
_In_ ACCESS_MASK DesiredAccess,
|
||||
_Out_ PHANDLE DataBlockHandle
|
||||
);
|
||||
|
||||
/**
|
||||
* The WmiQueryAllDataW function returns all WMI data blocks that implement a given WMI class (Unicode).
|
||||
*
|
||||
* \param DataBlockHandle Handle to a WMI data block object.
|
||||
* \param BufferLength Pointer to a memory location that specifies the size of the buffer.
|
||||
* \param Buffer Pointer to the buffer where the routine returns the WMI data.
|
||||
* \return ULONG Successful or errant status.
|
||||
*/
|
||||
NTSYSAPI ULONG NTAPI
|
||||
WmiQueryAllDataW(
|
||||
_In_ HANDLE DataBlockHandle,
|
||||
_Inout_ PULONG BufferLength,
|
||||
_Out_writes_bytes_opt_(*BufferLength) PVOID Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
* The WmiCloseBlock function closes a WMI data block object.
|
||||
*
|
||||
* \param DataBlockHandle Handle to the data block object to be closed.
|
||||
* \return ULONG Successful or errant status.
|
||||
*/
|
||||
NTSYSAPI ULONG NTAPI
|
||||
WmiCloseBlock(
|
||||
_In_ HANDLE DataBlockHandle
|
||||
);
|
||||
|
||||
static inline void ffCloseWmiBlock(HANDLE* hBlock) {
|
||||
assert(hBlock);
|
||||
if (*hBlock) {
|
||||
WmiCloseBlock(*hBlock);
|
||||
}
|
||||
}
|
||||
|
||||
#define FF_AUTO_CLOSE_WMI_BLOCK __attribute__((cleanup(ffCloseWmiBlock)))
|
||||
|
||||
// MOF: https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/km/wmicore.mof
|
||||
@@ -0,0 +1,227 @@
|
||||
#include "brightness.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/library.h"
|
||||
#include "common/mallocHelper.h"
|
||||
#include "common/windows/wmi.h"
|
||||
#include "common/windows/unicode.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <winternl.h>
|
||||
#include <windows.h>
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI GetPhysicalMonitors(
|
||||
_In_ UNICODE_STRING* pstrDeviceName,
|
||||
_In_ DWORD dwPhysicalMonitorArraySize,
|
||||
_Out_ DWORD* pdwNumPhysicalMonitorHandlesInArray,
|
||||
_Out_ HANDLE* phPhysicalMonitorArray);
|
||||
|
||||
typedef enum _MC_VCP_CODE_TYPE {
|
||||
MC_MOMENTARY,
|
||||
MC_SET_PARAMETER
|
||||
} MC_VCP_CODE_TYPE,
|
||||
*LPMC_VCP_CODE_TYPE;
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI DDCCIGetVCPFeature(
|
||||
_In_ HANDLE hMonitor,
|
||||
_In_ DWORD dwVCPCode,
|
||||
_Out_opt_ LPMC_VCP_CODE_TYPE pvct,
|
||||
_Out_ DWORD* pdwCurrentValue,
|
||||
_Out_opt_ DWORD* pdwMaximumValue);
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI DestroyPhysicalMonitorInternal(
|
||||
_In_ HANDLE hMonitor);
|
||||
|
||||
NTSTATUS WINAPI GetPhysicalMonitorDescription(
|
||||
_In_ HANDLE hMonitor,
|
||||
_In_ DWORD dwPhysicalMonitorDescriptionSizeInChars,
|
||||
_Out_ LPWSTR szPhysicalMonitorDescription);
|
||||
|
||||
static const char* detectWithWmi(FFlist* result) {
|
||||
FF_DEBUG("WMI: start detection");
|
||||
|
||||
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/km/wmicore.mof#L21200
|
||||
const GUID WmiMonitorBrightnessGuid = {
|
||||
0xd43412ac, 0x67f9, 0x4fbb, { 0xa0, 0x81, 0x17, 0x52, 0xa2, 0xc3, 0x3e, 0x84 }
|
||||
};
|
||||
|
||||
FF_AUTO_CLOSE_WMI_BLOCK HANDLE hBlock = NULL;
|
||||
|
||||
ULONG status = WmiOpenBlock(&WmiMonitorBrightnessGuid, WMIGUID_QUERY, &hBlock);
|
||||
if (status != 0) {
|
||||
FF_DEBUG("WMI: WmiOpenBlock failed, status=%lu, error=%s", status, ffDebugWin32Error(GetLastError()));
|
||||
return "WmiOpenBlock() failed";
|
||||
}
|
||||
|
||||
ULONG bufferSize = 0;
|
||||
status = WmiQueryAllDataW(hBlock, &bufferSize, NULL);
|
||||
if (status != ERROR_SUCCESS && status != ERROR_INSUFFICIENT_BUFFER) {
|
||||
FF_DEBUG("WMI: first WmiQueryAllDataW failed, status=%lu, bufferSize=%lu, error=%s", status, bufferSize, ffDebugWin32Error(GetLastError()));
|
||||
return "WmiQueryAllDataW() failed";
|
||||
}
|
||||
|
||||
FF_DEBUG("WMI: initial query status=%lu, bufferSize=%lu", status, bufferSize);
|
||||
|
||||
if (bufferSize == 0) {
|
||||
FF_DEBUG("WMI: WmiQueryAllDataW returned empty buffer");
|
||||
return "WmiQueryAllDataW() returned no data";
|
||||
}
|
||||
|
||||
FF_AUTO_FREE PWNODE_ALL_DATA pAllData = (PWNODE_ALL_DATA) malloc(bufferSize);
|
||||
if (!pAllData) {
|
||||
FF_DEBUG("WMI: malloc failed, bufferSize=%lu", bufferSize);
|
||||
return "malloc() failed";
|
||||
}
|
||||
|
||||
status = WmiQueryAllDataW(hBlock, &bufferSize, pAllData);
|
||||
if (status != ERROR_SUCCESS) {
|
||||
FF_DEBUG("WMI: second WmiQueryAllDataW failed, status=%lu, bufferSize=%lu, error=%s", status, bufferSize, ffDebugWin32Error(GetLastError()));
|
||||
return "WmiQueryAllDataW() failed";
|
||||
}
|
||||
|
||||
if (bufferSize < sizeof(WNODE_ALL_DATA)) {
|
||||
FF_DEBUG("WMI: insufficient buffer for WNODE_ALL_DATA, bufferSize=%lu", bufferSize);
|
||||
return "WmiQueryAllDataW() returned insufficient data for WNODE_ALL_DATA";
|
||||
}
|
||||
|
||||
FF_DEBUG("WMI: instanceCount=%lu, flags=0x%lX", pAllData->InstanceCount, pAllData->WnodeHeader.Flags);
|
||||
|
||||
PULONG pNameOffsets = (PULONG) ((PUCHAR) pAllData + pAllData->OffsetInstanceNameOffsets);
|
||||
|
||||
for (ULONG i = 0; i < pAllData->InstanceCount; i++) {
|
||||
ULONG dataOffset = 0;
|
||||
ULONG dataLength = 0;
|
||||
|
||||
if (pAllData->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
|
||||
dataLength = pAllData->FixedInstanceSize;
|
||||
dataOffset = pAllData->DataBlockOffset + i * dataLength;
|
||||
} else {
|
||||
dataOffset = pAllData->OffsetInstanceDataAndLength[i].OffsetInstanceData;
|
||||
dataLength = pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData;
|
||||
}
|
||||
|
||||
if (dataLength == 0 || dataOffset >= bufferSize || dataLength > bufferSize - dataOffset) {
|
||||
FF_DEBUG("WMI: skip invalid instance %lu (dataOffset=%lu, dataLength=%lu, bufferSize=%lu)", i, dataOffset, dataLength, bufferSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
USHORT nameCharsCount = *(PUSHORT) ((PUCHAR) pAllData + pNameOffsets[i]) / sizeof(WCHAR);
|
||||
PCWSTR pNameChars = (PCWSTR) ((PUCHAR) pAllData + (pNameOffsets[i] + sizeof(USHORT)));
|
||||
|
||||
PUCHAR pDataBlock = (PUCHAR) pAllData + dataOffset;
|
||||
UCHAR currentBrightness = pDataBlock[0];
|
||||
|
||||
FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = currentBrightness;
|
||||
brightness->builtin = true;
|
||||
ffStrbufInitNWS(&brightness->name, nameCharsCount, pNameChars);
|
||||
ffStrbufSubstrAfterFirstC(&brightness->name, '\\');
|
||||
ffStrbufSubstrBeforeFirstC(&brightness->name, '\\');
|
||||
|
||||
FF_DEBUG("WMI: detected builtin display '%s', current=%u", brightness->name.chars, (unsigned) currentBrightness);
|
||||
}
|
||||
|
||||
FF_DEBUG("WMI: finished detection, total results=%u", result->length);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) {
|
||||
FF_DEBUG("DDC/CI: start detection, displayCount=%u", displayServer->displays.length);
|
||||
|
||||
void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
|
||||
if (!gdi32) {
|
||||
FF_DEBUG("DDC/CI: failed to load gdi32.dll: %s", ffDebugWin32Error(GetLastError()));
|
||||
return "ffLibraryGetModule(gdi32.dll) failed";
|
||||
}
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)
|
||||
|
||||
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN) {
|
||||
FF_DEBUG("DDC/CI: skip builtin display id=%" PRIu64, display->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
MONITORINFOEXW mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (!GetMonitorInfoW((HMONITOR) (uintptr_t) display->id, (LPMONITORINFO) &mi)) {
|
||||
FF_DEBUG("DDC/CI: GetMonitorInfoW failed for display id=%" PRIu64 ": %s", display->id, ffDebugWin32Error(GetLastError()));
|
||||
continue;
|
||||
}
|
||||
|
||||
UNICODE_STRING deviceName = {
|
||||
.Length = (USHORT) (wcslen(mi.szDevice) * sizeof(wchar_t)),
|
||||
.MaximumLength = 0,
|
||||
.Buffer = mi.szDevice,
|
||||
};
|
||||
HANDLE physicalMonitor;
|
||||
DWORD monitorCount = 0;
|
||||
NTSTATUS monitorStatus = ffGetPhysicalMonitors(&deviceName, 1, &monitorCount, &physicalMonitor);
|
||||
if (NT_SUCCESS(monitorStatus) && monitorCount >= 1) {
|
||||
DWORD curr = 0, max = 0;
|
||||
if (NT_SUCCESS(ffDDCCIGetVCPFeature(physicalMonitor, 0x10 /* luminance */, NULL, &curr, &max))) {
|
||||
FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
|
||||
if (display->name.length > 0) {
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
} else {
|
||||
FF_LIBRARY_LOAD_SYMBOL_LAZY(gdi32, GetPhysicalMonitorDescription)
|
||||
if (ffGetPhysicalMonitorDescription) {
|
||||
wchar_t description[128 /*MUST be PHYSICAL_MONITOR_DESCRIPTION_SIZE*/];
|
||||
if (NT_SUCCESS(ffGetPhysicalMonitorDescription(physicalMonitor, ARRAY_SIZE(description), description))) {
|
||||
ffStrbufInitWS(&brightness->name, description);
|
||||
}
|
||||
}
|
||||
if (brightness->name.length == 0) {
|
||||
ffStrbufSetNWS(&brightness->name, deviceName.Length / 2, deviceName.Buffer);
|
||||
}
|
||||
}
|
||||
brightness->max = max;
|
||||
brightness->min = 0;
|
||||
brightness->current = curr;
|
||||
brightness->builtin = false;
|
||||
|
||||
FF_DEBUG("DDC/CI: detected external display '%s', current=%u, max=%u", brightness->name.chars, (unsigned) curr, (unsigned) max);
|
||||
} else {
|
||||
FF_DEBUG("DDC/CI: DDCCIGetVCPFeature failed for monitor '%ls': %s", deviceName.Buffer, ffDebugWin32Error(GetLastError()));
|
||||
}
|
||||
|
||||
ffDestroyPhysicalMonitorInternal(physicalMonitor);
|
||||
} else {
|
||||
FF_DEBUG("DDC/CI: GetPhysicalMonitors failed for '%ls', status=0x%08X, monitorCount=%lu, error=%s", deviceName.Buffer, (unsigned) monitorStatus, monitorCount, ffDebugWin32Error(GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
FF_DEBUG("DDC/CI: finished detection, total results=%u", result->length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer) {
|
||||
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* ffDetectBrightness(FF_A_UNUSED FFBrightnessOptions* options, FFlist* result) {
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
FF_DEBUG("start, displayCount=%u", displayServer->displays.length);
|
||||
|
||||
if (hasBuiltinDisplay(displayServer)) {
|
||||
FF_DEBUG("builtin display detected, trying WMI");
|
||||
detectWithWmi(result);
|
||||
}
|
||||
|
||||
if (result->length < displayServer->displays.length) {
|
||||
FF_DEBUG("resultCount=%u < displayCount=%u, trying DDC/CI", result->length, displayServer->displays.length);
|
||||
detectWithDdcci(displayServer, result);
|
||||
}
|
||||
|
||||
FF_DEBUG("finished, resultCount=%u", result->length);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
extern "C" {
|
||||
#include "brightness.h"
|
||||
#include "detection/displayserver/displayserver.h"
|
||||
#include "common/library.h"
|
||||
}
|
||||
#include "common/windows/wmi.hpp"
|
||||
#include "common/windows/unicode.hpp"
|
||||
|
||||
#include <winternl.h>
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI GetPhysicalMonitors(
|
||||
_In_ UNICODE_STRING* pstrDeviceName,
|
||||
_In_ DWORD dwPhysicalMonitorArraySize,
|
||||
_Out_ DWORD* pdwNumPhysicalMonitorHandlesInArray,
|
||||
_Out_ HANDLE* phPhysicalMonitorArray);
|
||||
|
||||
typedef enum _MC_VCP_CODE_TYPE {
|
||||
MC_MOMENTARY,
|
||||
MC_SET_PARAMETER
|
||||
} MC_VCP_CODE_TYPE,
|
||||
*LPMC_VCP_CODE_TYPE;
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI DDCCIGetVCPFeature(
|
||||
_In_ HANDLE hMonitor,
|
||||
_In_ DWORD dwVCPCode,
|
||||
_Out_opt_ LPMC_VCP_CODE_TYPE pvct,
|
||||
_Out_ DWORD* pdwCurrentValue,
|
||||
_Out_opt_ DWORD* pdwMaximumValue);
|
||||
|
||||
NTSYSAPI NTSTATUS WINAPI DestroyPhysicalMonitorInternal(
|
||||
_In_ HANDLE hMonitor);
|
||||
|
||||
NTSTATUS WINAPI GetPhysicalMonitorDescription(
|
||||
_In_ HANDLE hMonitor,
|
||||
_In_ DWORD dwPhysicalMonitorDescriptionSizeInChars,
|
||||
_Out_ LPWSTR szPhysicalMonitorDescription);
|
||||
|
||||
static const char* detectWithWmi(FFlist* result) {
|
||||
FFWmiQuery query(L"SELECT CurrentBrightness, InstanceName FROM WmiMonitorBrightness WHERE Active = true", nullptr, FFWmiNamespace::WMI);
|
||||
if (!query) {
|
||||
return "Query WMI service failed";
|
||||
}
|
||||
|
||||
while (FFWmiRecord record = query.next()) {
|
||||
if (FFWmiVariant vtValue = record.get(L"CurrentBrightness")) {
|
||||
FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
|
||||
brightness->max = 100;
|
||||
brightness->min = 0;
|
||||
brightness->current = vtValue.get<uint8_t>();
|
||||
brightness->builtin = true;
|
||||
|
||||
ffStrbufInit(&brightness->name);
|
||||
if (FFWmiVariant vtName = record.get(L"InstanceName")) {
|
||||
ffStrbufSetWSV(&brightness->name, vtName.get<std::wstring_view>());
|
||||
ffStrbufSubstrAfterFirstC(&brightness->name, '\\');
|
||||
ffStrbufSubstrBeforeFirstC(&brightness->name, '\\');
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) {
|
||||
void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
|
||||
if (!gdi32) {
|
||||
return "ffLibraryGetModule(gdi32.dll) failed";
|
||||
}
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
|
||||
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)
|
||||
|
||||
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MONITORINFOEXW mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (!GetMonitorInfoW((HMONITOR) (uintptr_t) display->id, (LPMONITORINFO) &mi)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UNICODE_STRING deviceName = {
|
||||
.Length = (USHORT) (wcslen(mi.szDevice) * sizeof(wchar_t)),
|
||||
.MaximumLength = 0,
|
||||
.Buffer = mi.szDevice,
|
||||
};
|
||||
HANDLE physicalMonitor;
|
||||
DWORD monitorCount = 0;
|
||||
if (NT_SUCCESS(ffGetPhysicalMonitors(&deviceName, 1, &monitorCount, &physicalMonitor)) && monitorCount >= 1) {
|
||||
DWORD curr = 0, max = 0;
|
||||
if (NT_SUCCESS(ffDDCCIGetVCPFeature(physicalMonitor, 0x10 /* luminance */, NULL, &curr, &max))) {
|
||||
FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
|
||||
if (display->name.length > 0) {
|
||||
ffStrbufInitCopy(&brightness->name, &display->name);
|
||||
} else {
|
||||
FF_LIBRARY_LOAD_SYMBOL_LAZY(gdi32, GetPhysicalMonitorDescription)
|
||||
if (ffGetPhysicalMonitorDescription) {
|
||||
wchar_t description[128 /*MUST be PHYSICAL_MONITOR_DESCRIPTION_SIZE*/];
|
||||
if (NT_SUCCESS(ffGetPhysicalMonitorDescription(physicalMonitor, ARRAY_SIZE(description), description))) {
|
||||
ffStrbufInitWS(&brightness->name, description);
|
||||
}
|
||||
}
|
||||
if (brightness->name.length == 0) {
|
||||
ffStrbufSetNWS(&brightness->name, deviceName.Length / 2, deviceName.Buffer);
|
||||
}
|
||||
}
|
||||
brightness->max = max;
|
||||
brightness->min = 0;
|
||||
brightness->current = curr;
|
||||
brightness->builtin = false;
|
||||
}
|
||||
|
||||
ffDestroyPhysicalMonitorInternal(physicalMonitor);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer) {
|
||||
FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
|
||||
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" const char* ffDetectBrightness(FF_A_UNUSED FFBrightnessOptions* options, FFlist* result) {
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
|
||||
if (hasBuiltinDisplay(displayServer)) {
|
||||
detectWithWmi(result);
|
||||
}
|
||||
|
||||
if (result->length < displayServer->displays.length) {
|
||||
detectWithDdcci(displayServer, result);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user