ohmu
·
2026-10-15
1#include "brightness.h"
2#include "detection/displayserver/displayserver.h"
3#include "common/debug.h"
4#include "common/library.h"
5#include "common/mallocHelper.h"
6#include "common/windows/wmi.h"
7#include "common/windows/unicode.h"
8
9#include <inttypes.h>
10#include <winternl.h>
11#include <windows.h>
12
13NTSYSAPI NTSTATUS WINAPI GetPhysicalMonitors(
14 _In_ UNICODE_STRING* pstrDeviceName,
15 _In_ DWORD dwPhysicalMonitorArraySize,
16 _Out_ DWORD* pdwNumPhysicalMonitorHandlesInArray,
17 _Out_ HANDLE* phPhysicalMonitorArray);
18
19typedef enum _MC_VCP_CODE_TYPE {
20 MC_MOMENTARY,
21 MC_SET_PARAMETER
22} MC_VCP_CODE_TYPE,
23 *LPMC_VCP_CODE_TYPE;
24
25NTSYSAPI NTSTATUS WINAPI DDCCIGetVCPFeature(
26 _In_ HANDLE hMonitor,
27 _In_ DWORD dwVCPCode,
28 _Out_opt_ LPMC_VCP_CODE_TYPE pvct,
29 _Out_ DWORD* pdwCurrentValue,
30 _Out_opt_ DWORD* pdwMaximumValue);
31
32NTSYSAPI NTSTATUS WINAPI DestroyPhysicalMonitorInternal(
33 _In_ HANDLE hMonitor);
34
35NTSTATUS WINAPI GetPhysicalMonitorDescription(
36 _In_ HANDLE hMonitor,
37 _In_ DWORD dwPhysicalMonitorDescriptionSizeInChars,
38 _Out_ LPWSTR szPhysicalMonitorDescription);
39
40static const char* detectWithWmi(FFlist* result) {
41 FF_DEBUG("WMI: start detection");
42
43 // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/km/wmicore.mof#L21200
44 const GUID WmiMonitorBrightnessGuid = {
45 0xd43412ac, 0x67f9, 0x4fbb, { 0xa0, 0x81, 0x17, 0x52, 0xa2, 0xc3, 0x3e, 0x84 }
46 };
47
48 [[gnu::cleanup(ffCloseWmiBlock)]] HANDLE hBlock = nullptr;
49
50 ULONG status = WmiOpenBlock(&WmiMonitorBrightnessGuid, WMIGUID_QUERY, &hBlock);
51 if (status != 0) {
52 FF_DEBUG("WMI: WmiOpenBlock failed: %s", ffDebugWin32Error(status));
53 return "WmiOpenBlock() failed";
54 }
55
56 ULONG bufferSize = 0;
57 status = WmiQueryAllDataW(hBlock, &bufferSize, nullptr);
58 if (status != ERROR_SUCCESS && status != ERROR_INSUFFICIENT_BUFFER) {
59 FF_DEBUG("WMI: first WmiQueryAllDataW failed, bufferSize=%lu: %s", bufferSize, ffDebugWin32Error(status));
60 return "WmiQueryAllDataW() failed";
61 }
62
63 FF_DEBUG("WMI: initial query bufferSize=%lu", bufferSize);
64
65 if (bufferSize == 0) {
66 FF_DEBUG("WMI: WmiQueryAllDataW returned empty buffer");
67 return "WmiQueryAllDataW() returned no data";
68 }
69
70 FF_AUTO_FREE PWNODE_ALL_DATA pAllData = (PWNODE_ALL_DATA) malloc(bufferSize);
71
72 status = WmiQueryAllDataW(hBlock, &bufferSize, pAllData);
73 if (status != ERROR_SUCCESS) {
74 FF_DEBUG("WMI: second WmiQueryAllDataW failed, bufferSize=%lu: %s", bufferSize, ffDebugWin32Error(status));
75 return "WmiQueryAllDataW() failed";
76 }
77
78 if (bufferSize < sizeof(WNODE_ALL_DATA)) {
79 FF_DEBUG("WMI: insufficient buffer for WNODE_ALL_DATA, bufferSize=%lu", bufferSize);
80 return "WmiQueryAllDataW() returned insufficient data for WNODE_ALL_DATA";
81 }
82
83 FF_DEBUG("WMI: instanceCount=%lu, flags=0x%lX", pAllData->InstanceCount, pAllData->WnodeHeader.Flags);
84
85 PULONG pNameOffsets = (PULONG) ((PUCHAR) pAllData + pAllData->OffsetInstanceNameOffsets);
86
87 for (ULONG i = 0; i < pAllData->InstanceCount; i++) {
88 ULONG dataOffset = 0;
89 ULONG dataLength = 0;
90
91 if (pAllData->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) {
92 dataLength = pAllData->FixedInstanceSize;
93 dataOffset = pAllData->DataBlockOffset + i * dataLength;
94 } else {
95 dataOffset = pAllData->OffsetInstanceDataAndLength[i].OffsetInstanceData;
96 dataLength = pAllData->OffsetInstanceDataAndLength[i].LengthInstanceData;
97 }
98
99 if (dataLength == 0 || dataOffset >= bufferSize || dataLength > bufferSize - dataOffset) {
100 FF_DEBUG("WMI: skip invalid instance %lu (dataOffset=%lu, dataLength=%lu, bufferSize=%lu)", i, dataOffset, dataLength, bufferSize);
101 continue;
102 }
103
104 USHORT nameCharsCount = *(PUSHORT) ((PUCHAR) pAllData + pNameOffsets[i]) / sizeof(WCHAR);
105 PCWSTR pNameChars = (PCWSTR) ((PUCHAR) pAllData + (pNameOffsets[i] + sizeof(USHORT)));
106
107 PUCHAR pDataBlock = (PUCHAR) pAllData + dataOffset;
108 UCHAR currentBrightness = pDataBlock[0];
109
110 FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
111 brightness->max = 100;
112 brightness->min = 0;
113 brightness->current = currentBrightness;
114 brightness->builtin = true;
115 ffStrbufInitNWS(&brightness->name, nameCharsCount, pNameChars);
116 ffStrbufSubstrAfterFirstC(&brightness->name, '\\');
117 ffStrbufSubstrBeforeFirstC(&brightness->name, '\\');
118
119 FF_DEBUG("WMI: detected builtin display '%s', current=%u", brightness->name.chars, (unsigned) currentBrightness);
120 }
121
122 FF_DEBUG("WMI: finished detection, total results=%u", result->length);
123
124 return nullptr;
125}
126
127static const char* detectWithDdcci(const FFDisplayServerResult* displayServer, FFlist* result) {
128 FF_DEBUG("DDC/CI: start detection, displayCount=%u", displayServer->displays.length);
129
130 void* gdi32 = ffLibraryGetModule(L"gdi32.dll");
131 if (!gdi32) {
132 FF_DEBUG("DDC/CI: failed to load gdi32.dll");
133 return "ffLibraryGetModule(gdi32.dll) failed";
134 }
135 FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, GetPhysicalMonitors)
136 FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DDCCIGetVCPFeature)
137 FF_LIBRARY_LOAD_SYMBOL_MESSAGE(gdi32, DestroyPhysicalMonitorInternal)
138
139 FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
140 if (display->type == FF_DISPLAY_TYPE_BUILTIN) {
141 FF_DEBUG("DDC/CI: skip builtin display id=%" PRIu64, display->id);
142 continue;
143 }
144
145 MONITORINFOEXW mi;
146 mi.cbSize = sizeof(mi);
147 if (!GetMonitorInfoW((HMONITOR) (uintptr_t) display->id, (LPMONITORINFO) &mi)) {
148 FF_DEBUG("DDC/CI: GetMonitorInfoW failed for display id=%" PRIu64 ": %s", display->id, ffDebugWin32Error(GetLastError()));
149 continue;
150 }
151
152 UNICODE_STRING deviceName = {
153 .Length = (USHORT) (wcslen(mi.szDevice) * sizeof(wchar_t)),
154 .MaximumLength = 0,
155 .Buffer = mi.szDevice,
156 };
157 HANDLE physicalMonitor;
158 DWORD monitorCount = 0;
159 NTSTATUS monitorStatus = ffGetPhysicalMonitors(&deviceName, 1, &monitorCount, &physicalMonitor);
160 if (NT_SUCCESS(monitorStatus) && monitorCount >= 1) {
161 DWORD curr = 0, max = 0;
162 monitorStatus = ffDDCCIGetVCPFeature(physicalMonitor, FF_DDC_CI_LUMINANCE_OPCODE, nullptr, &curr, &max);
163 if (NT_SUCCESS(monitorStatus)) {
164 FFBrightnessResult* brightness = FF_LIST_ADD(FFBrightnessResult, *result);
165 if (display->name.length > 0) {
166 ffStrbufInitCopy(&brightness->name, &display->name);
167 } else {
168 FF_LIBRARY_LOAD_SYMBOL_LAZY(gdi32, GetPhysicalMonitorDescription)
169 if (ffGetPhysicalMonitorDescription) {
170 wchar_t description[128 /*MUST be PHYSICAL_MONITOR_DESCRIPTION_SIZE*/];
171 monitorStatus = ffGetPhysicalMonitorDescription(physicalMonitor, ARRAY_SIZE(description), description);
172 if (NT_SUCCESS(monitorStatus)) {
173 ffStrbufInitWS(&brightness->name, description);
174 } else {
175 FF_DEBUG("DDC/CI: GetPhysicalMonitorDescription failed for monitor '%ls': %s", deviceName.Buffer, ffDebugNtStatus(monitorStatus));
176 }
177 }
178 if (brightness->name.length == 0) {
179 ffStrbufSetNWS(&brightness->name, deviceName.Length / 2, deviceName.Buffer);
180 }
181 }
182 brightness->max = max;
183 brightness->min = 0;
184 brightness->current = curr;
185 brightness->builtin = false;
186
187 FF_DEBUG("DDC/CI: detected external display '%s', current=%u, max=%u", brightness->name.chars, (unsigned) curr, (unsigned) max);
188 } else {
189 FF_DEBUG("DDC/CI: DDCCIGetVCPFeature failed for monitor '%ls': %s", deviceName.Buffer, ffDebugNtStatus(monitorStatus));
190 }
191
192 ffDestroyPhysicalMonitorInternal(physicalMonitor);
193 } else {
194 FF_DEBUG("DDC/CI: GetPhysicalMonitors failed for '%ls', status=0x%08X, monitorCount=%lu, error=%s", deviceName.Buffer, (unsigned) monitorStatus, monitorCount, ffDebugWin32Error(GetLastError()));
195 }
196 }
197
198 FF_DEBUG("DDC/CI: finished detection, total results=%u", result->length);
199 return nullptr;
200}
201
202static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer) {
203 FF_LIST_FOR_EACH (FFDisplayResult, display, displayServer->displays) {
204 if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN) {
205 return true;
206 }
207 }
208 return false;
209}
210
211const char* ffDetectBrightness([[maybe_unused]] FFBrightnessOptions* options, FFlist* result) {
212 const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
213 FF_DEBUG("start, displayCount=%u", displayServer->displays.length);
214
215 if (hasBuiltinDisplay(displayServer)) {
216 FF_DEBUG("builtin display detected, trying WMI");
217 detectWithWmi(result);
218 }
219
220 if (options->ddcciSleep != FF_BRIGHTNESS_DDCCI_SLEEP_SKIP && result->length < displayServer->displays.length) {
221 FF_DEBUG("resultCount=%u < displayCount=%u, trying DDC/CI", result->length, displayServer->displays.length);
222 detectWithDdcci(displayServer, result);
223 }
224
225 FF_DEBUG("finished, resultCount=%u", result->length);
226 return nullptr;
227}