diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a5122e76..f646f91d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -313,7 +313,7 @@ if(WIN_MSYS) src/detection/board/board_windows.cpp src/detection/os/os_linux.c src/detection/gpu/gpu_windows.cpp - src/detection/battery/battery_linux.c + src/detection/battery/battery_windows.cpp src/detection/displayserver/displayserver_windows.c src/detection/terminalfont/terminalfont_linux.c src/detection/media/media_linux.c diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index 2fc2b1d85..6a59625d7 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -1,10 +1,8 @@ #include "fastfetch.h" -#include "common/io.h" #include "battery.h" -#include - -const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) { +const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) +{ FF_UNUSED(instance, results) return "Unimplemented"; } diff --git a/src/detection/battery/battery_windows.cpp b/src/detection/battery/battery_windows.cpp new file mode 100644 index 000000000..9c84a3bf7 --- /dev/null +++ b/src/detection/battery/battery_windows.cpp @@ -0,0 +1,70 @@ +extern "C" { +#include "battery.h" +} +#include "util/windows/wmi.hpp" + +const char* ffDetectBatteryImpl(FFinstance* instance, FFlist* results) +{ + FF_UNUSED(instance); + + //https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-battery + IEnumWbemClassObject* pEnumerator = ffQueryWmi(L"SELECT SystemName, Name, Chemistry, EstimatedChargeRemaining, BatteryStatus FROM Win32_Battery", nullptr); + + if(!pEnumerator) + return "Query WMI service failed"; + + IWbemClassObject *pclsObj = NULL; + ULONG uReturn = 0; + + while(SUCCEEDED(pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn)) && uReturn != 0) + { + BatteryResult* battery = (BatteryResult*)ffListAdd(results); + + ffStrbufInit(&battery->manufacturer); + ffGetWmiObjValue(pclsObj, L"SystemName", &battery->manufacturer); + + ffStrbufInit(&battery->modelName); + ffGetWmiObjValue(pclsObj, L"Name", &battery->modelName); + + int64_t chemistry; + ffGetWmiObjInteger(pclsObj, L"Chemistry", &chemistry); + switch(chemistry) + { + case 1: ffStrbufInitS(&battery->technology, "Other"); break; + case 2: ffStrbufInitS(&battery->technology, "Unknown"); break; + case 3: ffStrbufInitS(&battery->technology, "Lead Acid"); break; + case 4: ffStrbufInitS(&battery->technology, "Nickel Cadmium"); break; + case 5: ffStrbufInitS(&battery->technology, "Nickel Metal Hydride"); break; + case 6: ffStrbufInitS(&battery->technology, "Lithium-ion"); break; + case 7: ffStrbufInitS(&battery->technology, "Zinc air"); break; + case 8: ffStrbufInitS(&battery->technology, "Lithium Polymer"); break; + } + + int64_t capacity; + ffGetWmiObjInteger(pclsObj, L"EstimatedChargeRemaining", &capacity); + ffStrbufInitF(&battery->capacity, "%d", (int)capacity); + + int64_t batteryStatus; + ffGetWmiObjInteger(pclsObj, L"BatteryStatus", &batteryStatus); + switch(batteryStatus) + { + case 1: ffStrbufInitS(&battery->status, "Discharging"); break; + case 2: ffStrbufInitS(&battery->status, "AC Connected"); break; + case 3: ffStrbufInitS(&battery->status, "Fully Charged"); break; + case 4: ffStrbufInitS(&battery->status, "Low"); break; + case 5: ffStrbufInitS(&battery->status, "Critical"); break; + case 6: ffStrbufInitS(&battery->status, "Charging"); break; + case 7: ffStrbufInitS(&battery->status, "Charging and High"); break; + case 8: ffStrbufInitS(&battery->status, "Charging and Low"); break; + case 9: ffStrbufInitS(&battery->status, "Charging and Critical"); break; + case 10: ffStrbufInitS(&battery->status, "Undefined"); break; + case 11: ffStrbufInitS(&battery->status, "Partially Charged"); break; + } + + battery->temperature = FF_BATTERY_TEMP_UNSET; + } + + pclsObj->Release(); + pEnumerator->Release(); + return nullptr; +} diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index a4938643d..30ba20a4f 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -197,3 +197,34 @@ bool ffGetWmiObjValue(IWbemClassObject* obj, const wchar_t* key, FFstrbuf* strbu VariantClear(&vtProp); return result; } + +bool ffGetWmiObjInteger(IWbemClassObject* obj, const wchar_t* key, int64_t* integer) +{ + bool result = true; + + VARIANT vtProp; + VariantInit(&vtProp); + + CIMTYPE type; + if(FAILED(obj->Get(key, 0, &vtProp, &type, nullptr))) + { + result = false; + } + else + { + switch(type) + { + case CIM_SINT8: *integer = vtProp.cVal; break; + case CIM_SINT16: *integer = vtProp.iVal; break; + case CIM_SINT32: *integer = vtProp.intVal; break; + case CIM_SINT64: *integer = vtProp.llVal; break; + case CIM_UINT8: *integer = (int64_t)vtProp.bVal; break; + case CIM_UINT16: *integer = (int64_t)vtProp.uiVal; break; + case CIM_UINT32: *integer = (int64_t)vtProp.uintVal; break; + case CIM_UINT64: *integer = (int64_t)vtProp.ullVal; break; + default: result = false; + } + } + VariantClear(&vtProp); + return result; +} diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 86d04099b..827fc88c6 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -34,6 +34,7 @@ void ffBstrToStrbuf(BSTR bstr, FFstrbuf* strbuf); IEnumWbemClassObject* ffQueryWmi(const wchar_t* queryStr, FFstrbuf* error); bool ffGetWmiObjValue(IWbemClassObject* obj, const wchar_t* key, FFstrbuf* strbuf); +bool ffGetWmiObjInteger(IWbemClassObject* obj, const wchar_t* key, int64_t* result); #else // Win32 COM headers requires C++ compiler