|
8 | 8 |
|
9 | 9 | #undef WIN32_LEAN_AND_MEAN |
10 | 10 | #include <windows.h> |
11 | | -#include <setupapi.h> |
12 | 11 | #include <batclass.h> |
13 | 12 | #include <devguid.h> |
| 13 | +#include <cfgmgr32.h> |
14 | 14 | #include <winternl.h> |
15 | 15 |
|
16 | | -static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev) |
| 16 | +static const char* detectWithCmApi(FFBatteryOptions* options, FFlist* results) |
17 | 17 | { |
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"; |
21 | 23 |
|
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"; |
42 | 31 |
|
| 32 | + for (const wchar_t* pDeviceInterface = mszDeviceInterfaces; *pDeviceInterface; pDeviceInterface += wcslen(pDeviceInterface) + 1) |
| 33 | + { |
43 | 34 | 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); |
45 | 36 |
|
46 | 37 | if(hBattery == INVALID_HANDLE_VALUE) |
47 | 38 | continue; |
@@ -99,7 +90,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results |
99 | 90 | bqi.InformationLevel = BatteryManufactureDate; |
100 | 91 | BATTERY_MANUFACTURE_DATE date; |
101 | 92 | 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); |
103 | 94 | } |
104 | 95 |
|
105 | 96 | { |
@@ -131,7 +122,7 @@ static const char* detectWithSetupApi(FFBatteryOptions* options, FFlist* results |
131 | 122 | { |
132 | 123 | BATTERY_STATUS bs; |
133 | 124 | 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) |
135 | 126 | battery->capacity = bs.Capacity * 100.0 / bi.FullChargedCapacity; |
136 | 127 | else |
137 | 128 | battery->capacity = 0; |
@@ -271,6 +262,6 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF |
271 | 262 | const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) |
272 | 263 | { |
273 | 264 | return options->useSetupApi |
274 | | - ? detectWithSetupApi(options, results) |
| 265 | + ? detectWithCmApi(options, results) |
275 | 266 | : detectWithNtApi(options, results); |
276 | 267 | } |
0 commit comments