@@ -30,137 +30,146 @@ static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
30
30
SetupDiDestroyDeviceInfoList (* hdev );
31
31
}
32
32
33
- const char * ffDetectBattery (FFBatteryOptions * options , FFlist * results )
33
+ static const char * detectWithSetupApi (FFBatteryOptions * options , FFlist * results )
34
34
{
35
- if (options -> useSetupApi )
35
+ //https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
36
+ HDEVINFO hdev __attribute__((__cleanup__ (wrapSetupDiDestroyDeviceInfoList ))) =
37
+ SetupDiGetClassDevsW (& GUID_DEVCLASS_BATTERY , 0 , 0 , DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
38
+ if (hdev == INVALID_HANDLE_VALUE )
39
+ return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed" ;
40
+
41
+ SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof (did ) };
42
+ for (DWORD idev = 0 ; SetupDiEnumDeviceInterfaces (hdev , NULL , & GUID_DEVCLASS_BATTERY , idev , & did ); idev ++ )
36
43
{
37
- //https://learn.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
38
- HDEVINFO hdev __attribute__((__cleanup__ (wrapSetupDiDestroyDeviceInfoList ))) =
39
- SetupDiGetClassDevsW (& GUID_DEVCLASS_BATTERY , 0 , 0 , DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
40
- if (hdev == INVALID_HANDLE_VALUE )
41
- return "SetupDiGetClassDevsW(&GUID_DEVCLASS_BATTERY) failed" ;
42
-
43
- SP_DEVICE_INTERFACE_DATA did = { .cbSize = sizeof (did ) };
44
- for (DWORD idev = 0 ; SetupDiEnumDeviceInterfaces (hdev , NULL , & GUID_DEVCLASS_BATTERY , idev , & did ); idev ++ )
44
+ DWORD cbRequired = 0 ;
45
+ SetupDiGetDeviceInterfaceDetailW (hdev , & did , NULL , 0 , & cbRequired , NULL ); //Fail with not enough buffer
46
+ SP_DEVICE_INTERFACE_DETAIL_DATA_W * FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W * )malloc (cbRequired );
47
+ if (!pdidd )
48
+ break ; //Out of memory
49
+
50
+ pdidd -> cbSize = sizeof (* pdidd );
51
+ if (!SetupDiGetDeviceInterfaceDetailW (hdev , & did , pdidd , cbRequired , & cbRequired , NULL ))
52
+ continue ;
53
+
54
+ HANDLE __attribute__((__cleanup__ (wrapCloseHandle ))) hBattery =
55
+ CreateFileW (pdidd -> DevicePath , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
56
+
57
+ if (hBattery == INVALID_HANDLE_VALUE )
58
+ continue ;
59
+
60
+ BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
61
+
62
+ DWORD dwWait = 0 ;
63
+ DWORD dwOut ;
64
+
65
+ if (!DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_TAG , & dwWait , sizeof (dwWait ), & bqi .BatteryTag , sizeof (bqi .BatteryTag ), & dwOut , NULL ) && bqi .BatteryTag )
66
+ continue ;
67
+
68
+ BATTERY_INFORMATION bi = {0 };
69
+ if (!DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), & bi , sizeof (bi ), & dwOut , NULL ))
70
+ continue ;
71
+
72
+ if (!(bi .Capabilities & BATTERY_SYSTEM_BATTERY ))
73
+ continue ;
74
+
75
+ FFBatteryResult * battery = (FFBatteryResult * )ffListAdd (results );
76
+
77
+ if (memcmp (bi .Chemistry , "PbAc" , 4 ) == 0 )
78
+ ffStrbufInitS (& battery -> technology , "Lead Acid" );
79
+ else if (memcmp (bi .Chemistry , "LION" , 4 ) == 0 || memcmp (bi .Chemistry , "Li-I" , 4 ) == 0 )
80
+ ffStrbufInitS (& battery -> technology , "Lithium Ion" );
81
+ else if (memcmp (bi .Chemistry , "NiCd" , 4 ) == 0 )
82
+ ffStrbufInitS (& battery -> technology , "Nickel Cadmium" );
83
+ else if (memcmp (bi .Chemistry , "NiMH" , 4 ) == 0 )
84
+ ffStrbufInitS (& battery -> technology , "Nickel Metal Hydride" );
85
+ else if (memcmp (bi .Chemistry , "NiZn" , 4 ) == 0 )
86
+ ffStrbufInitS (& battery -> technology , "Nickel Zinc" );
87
+ else if (memcmp (bi .Chemistry , "RAM\0" , 4 ) == 0 )
88
+ ffStrbufInitS (& battery -> technology , "Rechargeable Alkaline-Manganese" );
89
+ else
90
+ ffStrbufInitS (& battery -> technology , "Unknown" );
91
+
92
+ {
93
+ ffStrbufInit (& battery -> modelName );
94
+ bqi .InformationLevel = BatteryDeviceName ;
95
+ wchar_t name [64 ];
96
+ if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), name , sizeof (name ), & dwOut , NULL ))
97
+ ffStrbufSetWS (& battery -> modelName , name );
98
+ }
99
+
100
+ {
101
+ ffStrbufInit (& battery -> manufacturer );
102
+ bqi .InformationLevel = BatteryManufactureName ;
103
+ wchar_t name [64 ];
104
+ if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), name , sizeof (name ), & dwOut , NULL ))
105
+ ffStrbufSetWS (& battery -> manufacturer , name );
106
+ }
107
+
108
+ battery -> cycleCount = bi .CycleCount ;
109
+
110
+ battery -> temperature = 0.0 /0.0 ;
111
+ if (options -> temp )
112
+ {
113
+ bqi .InformationLevel = BatteryTemperature ;
114
+ ULONG temp ;
115
+ if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), & temp , sizeof (temp ), & dwOut , NULL ))
116
+ battery -> temperature = temp ;
117
+ }
118
+
45
119
{
46
- DWORD cbRequired = 0 ;
47
- SetupDiGetDeviceInterfaceDetailW (hdev , & did , NULL , 0 , & cbRequired , NULL ); //Fail with not enough buffer
48
- SP_DEVICE_INTERFACE_DETAIL_DATA_W * FF_AUTO_FREE pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA_W * )malloc (cbRequired );
49
- if (!pdidd )
50
- break ; //Out of memory
51
-
52
- pdidd -> cbSize = sizeof (* pdidd );
53
- if (!SetupDiGetDeviceInterfaceDetailW (hdev , & did , pdidd , cbRequired , & cbRequired , NULL ))
54
- continue ;
55
-
56
- HANDLE __attribute__((__cleanup__ (wrapCloseHandle ))) hBattery =
57
- CreateFileW (pdidd -> DevicePath , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
58
-
59
- if (hBattery == INVALID_HANDLE_VALUE )
60
- continue ;
61
-
62
- BATTERY_QUERY_INFORMATION bqi = { .InformationLevel = BatteryInformation };
63
-
64
- DWORD dwWait = 0 ;
65
- DWORD dwOut ;
66
-
67
- if (!DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_TAG , & dwWait , sizeof (dwWait ), & bqi .BatteryTag , sizeof (bqi .BatteryTag ), & dwOut , NULL ) && bqi .BatteryTag )
68
- continue ;
69
-
70
- BATTERY_INFORMATION bi = {0 };
71
- if (!DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), & bi , sizeof (bi ), & dwOut , NULL ))
72
- continue ;
73
-
74
- if (!(bi .Capabilities & BATTERY_SYSTEM_BATTERY ))
75
- continue ;
76
-
77
- FFBatteryResult * battery = (FFBatteryResult * )ffListAdd (results );
78
-
79
- if (memcmp (bi .Chemistry , "PbAc" , 4 ) == 0 )
80
- ffStrbufInitS (& battery -> technology , "Lead Acid" );
81
- else if (memcmp (bi .Chemistry , "LION" , 4 ) == 0 || memcmp (bi .Chemistry , "Li-I" , 4 ) == 0 )
82
- ffStrbufInitS (& battery -> technology , "Lithium Ion" );
83
- else if (memcmp (bi .Chemistry , "NiCd" , 4 ) == 0 )
84
- ffStrbufInitS (& battery -> technology , "Nickel Cadmium" );
85
- else if (memcmp (bi .Chemistry , "NiMH" , 4 ) == 0 )
86
- ffStrbufInitS (& battery -> technology , "Nickel Metal Hydride" );
87
- else if (memcmp (bi .Chemistry , "NiZn" , 4 ) == 0 )
88
- ffStrbufInitS (& battery -> technology , "Nickel Zinc" );
89
- else if (memcmp (bi .Chemistry , "RAM\0" , 4 ) == 0 )
90
- ffStrbufInitS (& battery -> technology , "Rechargeable Alkaline-Manganese" );
120
+ BATTERY_STATUS bs ;
121
+ BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi .BatteryTag };
122
+ if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_STATUS , & bws , sizeof (bws ), & bs , sizeof (bs ), & dwOut , NULL ) && bs .Capacity != BATTERY_UNKNOWN_CAPACITY )
123
+ battery -> capacity = bs .Capacity * 100.0 / bi .FullChargedCapacity ;
91
124
else
92
- ffStrbufInitS (& battery -> technology , "Unknown" );
93
-
94
- {
95
- ffStrbufInit (& battery -> modelName );
96
- bqi .InformationLevel = BatteryDeviceName ;
97
- wchar_t name [64 ];
98
- if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), name , sizeof (name ), & dwOut , NULL ))
99
- ffStrbufSetWS (& battery -> modelName , name );
100
- }
101
-
102
- {
103
- ffStrbufInit (& battery -> manufacturer );
104
- bqi .InformationLevel = BatteryManufactureName ;
105
- wchar_t name [64 ];
106
- if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), name , sizeof (name ), & dwOut , NULL ))
107
- ffStrbufSetWS (& battery -> manufacturer , name );
108
- }
109
-
110
- battery -> temperature = 0.0 /0.0 ;
111
- if (options -> temp )
112
- {
113
- bqi .InformationLevel = BatteryTemperature ;
114
- ULONG temp ;
115
- if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_INFORMATION , & bqi , sizeof (bqi ), & temp , sizeof (temp ), & dwOut , NULL ))
116
- battery -> temperature = temp ;
117
- }
118
-
119
- {
120
- BATTERY_STATUS bs ;
121
- BATTERY_WAIT_STATUS bws = { .BatteryTag = bqi .BatteryTag };
122
- if (DeviceIoControl (hBattery , IOCTL_BATTERY_QUERY_STATUS , & bws , sizeof (bws ), & bs , sizeof (bs ), & dwOut , NULL ) && bs .Capacity != BATTERY_UNKNOWN_CAPACITY )
123
- battery -> capacity = bs .Capacity * 100.0 / bi .FullChargedCapacity ;
124
- else
125
- battery -> capacity = 0 ;
126
-
127
- ffStrbufInit (& battery -> status );
128
- if (bs .PowerState & BATTERY_POWER_ON_LINE )
129
- ffStrbufAppendS (& battery -> status , "AC Connected, " );
130
- if (bs .PowerState & BATTERY_DISCHARGING )
131
- ffStrbufAppendS (& battery -> status , "Discharging, " );
132
- if (bs .PowerState & BATTERY_CHARGING )
133
- ffStrbufAppendS (& battery -> status , "Charging" );
134
- if (bs .PowerState & BATTERY_CRITICAL )
135
- ffStrbufAppendS (& battery -> status , "Critical, " );
136
- ffStrbufTrimRight (& battery -> status , ' ' );
137
- ffStrbufTrimRight (& battery -> status , ',' );
138
- }
125
+ battery -> capacity = 0 ;
126
+
127
+ ffStrbufInit (& battery -> status );
128
+ if (bs .PowerState & BATTERY_POWER_ON_LINE )
129
+ ffStrbufAppendS (& battery -> status , "AC Connected, " );
130
+ if (bs .PowerState & BATTERY_DISCHARGING )
131
+ ffStrbufAppendS (& battery -> status , "Discharging, " );
132
+ if (bs .PowerState & BATTERY_CHARGING )
133
+ ffStrbufAppendS (& battery -> status , "Charging, " );
134
+ if (bs .PowerState & BATTERY_CRITICAL )
135
+ ffStrbufAppendS (& battery -> status , "Critical, " );
136
+ ffStrbufTrimRight (& battery -> status , ' ' );
137
+ ffStrbufTrimRight (& battery -> status , ',' );
139
138
}
140
139
}
141
- else
140
+ return NULL ;
141
+ }
142
+
143
+ static const char * detectWithNtApi (FFBatteryOptions * options , FFlist * results )
144
+ {
145
+ SYSTEM_BATTERY_STATE info ;
146
+ if (NT_SUCCESS (NtPowerInformation (SystemBatteryState , NULL , 0 , & info , sizeof (info ))) && info .BatteryPresent )
142
147
{
143
- SYSTEM_BATTERY_STATE info ;
144
- if (NT_SUCCESS (NtPowerInformation (SystemBatteryState , NULL , 0 , & info , sizeof (info ))) && info .BatteryPresent )
148
+ FFBatteryResult * battery = (FFBatteryResult * )ffListAdd (results );
149
+ ffStrbufInit (& battery -> modelName );
150
+ ffStrbufInit (& battery -> manufacturer );
151
+ ffStrbufInit (& battery -> technology );
152
+ ffStrbufInit (& battery -> status );
153
+ battery -> temperature = 0.0 /0.0 ;
154
+ battery -> cycleCount = 0 ;
155
+
156
+ battery -> capacity = info .RemainingCapacity * 100.0 / info .MaxCapacity ;
157
+ if (info .AcOnLine )
145
158
{
146
- FFBatteryResult * battery = (FFBatteryResult * )ffListAdd (results );
147
- ffStrbufInit (& battery -> modelName );
148
- ffStrbufInit (& battery -> manufacturer );
149
- ffStrbufInit (& battery -> technology );
150
- ffStrbufInit (& battery -> status );
151
- battery -> temperature = 0.0 /0.0 ;
152
-
153
- battery -> capacity = info .RemainingCapacity * 100.0 / info .MaxCapacity ;
154
- if (info .AcOnLine )
155
- {
156
- ffStrbufAppendS (& battery -> status , "AC Connected" );
157
- if (info .Charging )
158
- ffStrbufAppendS (& battery -> status , ", Charging" );
159
- }
160
- else if (info .Discharging )
161
- ffStrbufAppendS (& battery -> status , "Discharging" );
159
+ ffStrbufAppendS (& battery -> status , "AC Connected" );
160
+ if (info .Charging )
161
+ ffStrbufAppendS (& battery -> status , ", Charging" );
162
162
}
163
+ else if (info .Discharging )
164
+ ffStrbufAppendS (& battery -> status , "Discharging" );
165
+ return NULL ;
163
166
}
167
+ return "NtPowerInformation(SystemBatteryState) failed" ;
168
+ }
164
169
165
- return NULL ;
170
+ const char * ffDetectBattery (FFBatteryOptions * options , FFlist * results )
171
+ {
172
+ return true
173
+ ? detectWithSetupApi (options , results )
174
+ : detectWithNtApi (options , results );
166
175
}
0 commit comments