Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- v2: Skip tests on Wine on Mac OS --- dlls/kernel32/tests/Makefile.in | 1 + dlls/kernel32/tests/power.c | 83 +++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 dlls/kernel32/tests/power.c
diff --git a/dlls/kernel32/tests/Makefile.in b/dlls/kernel32/tests/Makefile.in index e06141d9f6..e9516603ce 100644 --- a/dlls/kernel32/tests/Makefile.in +++ b/dlls/kernel32/tests/Makefile.in @@ -25,6 +25,7 @@ SOURCES = \ module.c \ path.c \ pipe.c \ + power.c \ process.c \ profile.c \ resource.c \ diff --git a/dlls/kernel32/tests/power.c b/dlls/kernel32/tests/power.c new file mode 100644 index 0000000000..af488849e2 --- /dev/null +++ b/dlls/kernel32/tests/power.c @@ -0,0 +1,83 @@ +/* + * Unit tests for power management functions + * + * Copyright (c) 2019 Alex Henrie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" + +void test_GetSystemPowerStatus(void) +{ + SYSTEM_POWER_STATUS ps; + BOOL ret; + BYTE capacity_flags, expected_capacity_flags; + + if (0) /* crashes */ + GetSystemPowerStatus(NULL); + + memset(&ps, 0x23, sizeof(ps)); + ret = GetSystemPowerStatus(&ps); + ok(ret == TRUE, "expected TRUE\n"); + + if (ps.BatteryFlag == BATTERY_FLAG_UNKNOWN) + { + skip("GetSystemPowerStatus not implemented or not working\n"); + return; + } + else if (ps.BatteryFlag != BATTERY_FLAG_NO_BATTERY) + { + trace("battery detected\n"); + expected_capacity_flags = 0; + if (ps.BatteryLifePercent > 66) + expected_capacity_flags |= BATTERY_FLAG_HIGH; + if (ps.BatteryLifePercent < 33) + expected_capacity_flags |= BATTERY_FLAG_LOW; + if (ps.BatteryLifePercent < 5) + expected_capacity_flags |= BATTERY_FLAG_CRITICAL; + capacity_flags = (ps.BatteryFlag & ~BATTERY_FLAG_CHARGING); + ok(capacity_flags == expected_capacity_flags, + "expected %u%%-charged battery to have capacity flags 0x%02x, got 0x%02x\n", + ps.BatteryLifePercent, expected_capacity_flags, capacity_flags); + ok(ps.BatteryLifeTime <= ps.BatteryFullLifeTime, + "expected BatteryLifeTime %u to be less than or equal to BatteryFullLifeTime %u\n", + ps.BatteryLifeTime, ps.BatteryFullLifeTime); + if (ps.BatteryFlag & BATTERY_FLAG_CHARGING) + { + ok(ps.BatteryLifeTime == BATTERY_LIFE_UNKNOWN, + "expected BatteryLifeTime to be -1 when charging, got %u\n", ps.BatteryLifeTime); + ok(ps.BatteryFullLifeTime == BATTERY_LIFE_UNKNOWN, + "expected BatteryFullLifeTime to be -1 when charging, got %u\n", ps.BatteryFullLifeTime); + } + } + else + { + trace("no battery detected\n"); + ok(ps.ACLineStatus == AC_LINE_ONLINE, + "expected ACLineStatus to be 1, got %u\n", ps.ACLineStatus); + ok(ps.BatteryLifePercent == BATTERY_PERCENTAGE_UNKNOWN, + "expected BatteryLifePercent to be -1, got %u\n", ps.BatteryLifePercent); + ok(ps.BatteryLifeTime == BATTERY_LIFE_UNKNOWN, + "expected BatteryLifeTime to be -1, got %u\n", ps.BatteryLifeTime); + ok(ps.BatteryFullLifeTime == BATTERY_LIFE_UNKNOWN, + "expected BatteryFullLifeTime to be -1, got %u\n", ps.BatteryFullLifeTime); + } +} + +START_TEST(power) +{ + test_GetSystemPowerStatus(); +}
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- v2: Only return FALSE if there was an error other than SystemBatteryState not being implemented --- dlls/kernel32/powermgnt.c | 48 +++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/powermgnt.c b/dlls/kernel32/powermgnt.c index 7efd84d410..be03bb32e4 100644 --- a/dlls/kernel32/powermgnt.c +++ b/dlls/kernel32/powermgnt.c @@ -45,19 +45,47 @@ BOOL WINAPI GetDevicePowerState(HANDLE hDevice, BOOL* pfOn) */ BOOL WINAPI GetSystemPowerStatus(LPSYSTEM_POWER_STATUS ps) { - WARN("(%p): stub, harmless.\n", ps); + SYSTEM_BATTERY_STATE bs; + NTSTATUS status; + + TRACE("(%p)\n", ps); + + ps->ACLineStatus = AC_LINE_UNKNOWN; + ps->BatteryFlag = BATTERY_FLAG_UNKNOWN; + ps->BatteryLifePercent = BATTERY_PERCENTAGE_UNKNOWN; + ps->SystemStatusFlag = 0; + ps->BatteryLifeTime = BATTERY_LIFE_UNKNOWN; + ps->BatteryFullLifeTime = BATTERY_LIFE_UNKNOWN; + + status = NtPowerInformation(SystemBatteryState, NULL, 0, &bs, sizeof(bs)); + if (FAILED(status) && status != STATUS_NOT_IMPLEMENTED) + return FALSE; + + ps->ACLineStatus = bs.AcOnLine;
- if (ps) + if (bs.BatteryPresent) { - ps->ACLineStatus = 255; - ps->BatteryFlag = 255; - ps->BatteryLifePercent = 255; - ps->SystemStatusFlag = 0; - ps->BatteryLifeTime = ~0u; - ps->BatteryFullLifeTime = ~0u; - return TRUE; + ps->BatteryLifePercent = bs.MaxCapacity ? bs.RemainingCapacity / bs.MaxCapacity : 100; + ps->BatteryLifeTime = bs.EstimatedTime; + if (!bs.Charging && (LONG)bs.Rate < 0) + ps->BatteryFullLifeTime = 3600 * bs.MaxCapacity / -(LONG)bs.Rate; + + ps->BatteryFlag = 0; + if (bs.Charging) + ps->BatteryFlag |= BATTERY_FLAG_CHARGING; + if (ps->BatteryLifePercent > 66) + ps->BatteryFlag |= BATTERY_FLAG_HIGH; + if (ps->BatteryLifePercent < 33) + ps->BatteryFlag |= BATTERY_FLAG_LOW; + if (ps->BatteryLifePercent < 5) + ps->BatteryFlag |= BATTERY_FLAG_CRITICAL; } - return FALSE; + else + { + ps->BatteryFlag = BATTERY_FLAG_NO_BATTERY; + } + + return TRUE; }
/***********************************************************************