Skip to content

Commit c65fb1a

Browse files
committed
Battery (Windows): use CMAPI instead of SetupAPI
1 parent 2029679 commit c65fb1a

1 file changed

Lines changed: 20 additions & 29 deletions

File tree

src/detection/battery/battery_windows.c

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,31 @@
88

99
#undef WIN32_LEAN_AND_MEAN
1010
#include <windows.h>
11-
#include <setupapi.h>
1211
#include <batclass.h>
1312
#include <devguid.h>
13+
#include <cfgmgr32.h>
1414
#include <winternl.h>
1515

16-
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
16+
static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results)
1717
{
18-
if(*hdev)
19-
SetupDiDestroyDeviceInfoList(*hdev);
20-
}
18+
//https://learn.microsoft.com/en-us/windows-hardware/drivers/install/using-device-interfaces
19+
ULONG cchDeviceInterfaces = 0;
20+
CONFIGRET cr = CM_Get_Device_Interface_List_SizeW(&cchDeviceInterfaces, (LPGUID)&GUID_DEVCLASS_BATTERY, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
21+
if (cr != CR_SUCCESS)
22+
return "CM_Get_Device_Interface_List_SizeW() failed";
2123

22-
static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results)
23-
{
24-
//https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
25-
HDEVINFO hdev __attribute__((__cleanup__(wrapSetupDiDestroyDeviceInfoList))) =
26-
SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
27-
if(hdev == INVALID_HANDLE_VALUE)
28-
return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed";
29-
30-
SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof(did) };
31-
for(DWORD idev = 0; SetupDiEnumDeviceInterfaces(hdev, NULL, &GUID_DEVCLASS_BATTERY, idev, &did); idev++)
32-
{
33-
DWORD cbRequired = 0;
34-
SetupDiGetDeviceInterfaceDetailW(hdev, &did, NULL, 0, &cbRequired, NULL); //Fail with not enough buffer
35-
SP_DEVICE_INTERFACE_DETAIL_DATA_W* FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(cbRequired);
36-
if(!pdidd)
37-
break; //Out of memory
38-
39-
pdidd->cbSize = sizeof(*pdidd);
40-
if(!SetupDiGetDeviceInterfaceDetailW(hdev, &did, pdidd, cbRequired, &cbRequired, NULL))
41-
continue;
24+
if (cchDeviceInterfaces <= 1)
25+
return NULL; // Not found
26+
27+
wchar_t* FF_AUTO_FREE mszDeviceInterfaces = (wchar_t*)malloc(cchDeviceInterfaces * sizeof(wchar_t));
28+
cr = CM_Get_Device_Interface_ListW((LPGUID)&GUID_DEVCLASS_BATTERY, NULL, mszDeviceInterfaces, cchDeviceInterfaces, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
29+
if (cr != CR_SUCCESS)
30+
return "CM_Get_Device_Interface_ListW() failed";
4231

32+
for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1)
33+
{
4334
HANDLE FF_AUTO_CLOSE_FD hBattery =
44-
CreateFileW(pdidd->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
35+
CreateFileW(pDeviceInterface, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
4536

4637
if(hBattery == INVALID_HANDLE_VALUE)
4738
continue;
@@ -99,7 +90,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
9990
bqi.InformationLevel = BatteryManufactureDate;
10091
BATTERY_MANUFACTURE_DATE date;
10192
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_INFORMATION, &bqi, sizeof(bqi), &date, sizeof(date), &dwOut, NULL))
102-
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year + 1900, date.Month, date.Day);
93+
ffStrbufSetF(&battery->manufactureDate, "%.4d-%.2d-%.2d", date.Year < 1000 ? date.Year + 1900 : date.Year, date.Month, date.Day);
10394
}
10495

10596
{
@@ -131,7 +122,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results
131122
{
132123
BATTERY_STATUS bs;
133124
BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi.BatteryTag };
134-
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY)
125+
if(DeviceIoControl(hBattery, IOCTL_BATTERY_QUERY_STATUS, &bws, sizeof(bws), &bs, sizeof(bs), &dwOut, NULL) && bs.Capacity != BATTERY_UNKNOWN_CAPACITY && bi.FullChargedCapacity != 0)
135126
battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity;
136127
else
137128
battery->capacity = 0;
@@ -271,6 +262,6 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF
271262
const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results)
272263
{
273264
return options->useSetupApi
274-
? detectWithSetupApi(options, results)
265+
? detectWithCmApi(options, results)
275266
: detectWithNtApi(options, results);
276267
}

0 commit comments

Comments
 (0)