Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions ProjectReunion.sln
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,25 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PushNotificationTests", "te
{5B2D17FE-C371-417F-860C-3D32397C2404} = {5B2D17FE-C371-417F-860C-3D32397C2404}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerNotifications", "dev\PowerNotifications\PowerNotifications.vcxitems", "{3418759E-FB57-41A1-A485-9F7A363510E4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerNotifications", "test\PowerNotifications\PowerNotifications.vcxproj", "{CBD95746-61CE-4F31-B6CC-C5ABF1766180}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PowerNotifications", "PowerNotifications", "{067DB9CB-86B2-4DBB-A3EA-DB9D7078314C}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
test\inc\inc.vcxitems*{0a5fee93-48b7-40ec-bb9a-b27d11060da9}*SharedItemsImports = 4
dev\PushNotifications\PushNotifications.vcxitems*{103c0c23-7ba8-4d44-a63c-83488e2e3a81}*SharedItemsImports = 9
dev\PowerNotifications\PowerNotifications.vcxitems*{3418759e-fb57-41a1-a485-9f7a363510e4}*SharedItemsImports = 9
dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{56371ca6-144b-4989-a4e9-391ad4fa7651}*SharedItemsImports = 9
test\inc\inc.vcxitems*{56a1d696-feda-4333-bf37-772ebececb10}*SharedItemsImports = 4
test\inc\inc.vcxitems*{7c502995-59c3-483b-86ba-815985353633}*SharedItemsImports = 4
test\inc\inc.vcxitems*{8e52d7ea-a200-4a6b-ba74-8efb49468caf}*SharedItemsImports = 4
test\inc\inc.vcxitems*{b567fe2e-3a03-48d0-b2b5-760cdec35891}*SharedItemsImports = 9
dev\Common\Common.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
dev\DynamicDependency\DynamicDependency.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
dev\PowerNotifications\PowerNotifications.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
dev\UndockedRegFreeWinRT\UndockedRegFreeWinRT.vcxitems*{b73ad907-6164-4294-88fb-f3c9c10da1f1}*SharedItemsImports = 4
dev\DynamicDependency\DynamicDependency.vcxitems*{bf055a59-0919-4e34-9b76-dd055495cc5a}*SharedItemsImports = 9
test\inc\inc.vcxitems*{c62688a1-16a0-4729-b6ed-842f4faa29f3}*SharedItemsImports = 4
Expand Down Expand Up @@ -567,6 +575,18 @@ Global
{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x64.Build.0 = Release|x64
{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x86.ActiveCfg = Release|Win32
{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9}.Release|x86.Build.0 = Release|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|Any CPU.ActiveCfg = Debug|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|ARM64.ActiveCfg = Debug|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|x64.ActiveCfg = Debug|x64
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|x64.Build.0 = Debug|x64
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|x86.ActiveCfg = Debug|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Debug|x86.Build.0 = Debug|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|Any CPU.ActiveCfg = Release|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|ARM64.ActiveCfg = Release|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|x64.ActiveCfg = Release|x64
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|x64.Build.0 = Release|x64
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|x86.ActiveCfg = Release|Win32
{CBD95746-61CE-4F31-B6CC-C5ABF1766180}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -613,6 +633,9 @@ Global
{56A1D696-FEDA-4333-BF37-772EBECECB10} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440}
{D012E4BB-F16B-472D-A26D-D449CEFA988E} = {AC5FFC80-92FE-4933-BED2-EC5519AC4440}
{0A5FEE93-48B7-40EC-BB9A-B27D11060DA9} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{3418759E-FB57-41A1-A485-9F7A363510E4} = {067DB9CB-86B2-4DBB-A3EA-DB9D7078314C}
{CBD95746-61CE-4F31-B6CC-C5ABF1766180} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{067DB9CB-86B2-4DBB-A3EA-DB9D7078314C} = {448ED2E5-0B37-4D97-9E6B-8C10A507976A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77}
Expand Down
321 changes: 321 additions & 0 deletions dev/PowerNotifications/PowerNotifications.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include <pch.h>
#include <future>
#include <PowerNotifications.h>
#include <frameworkudk\PowerNotificationsPal.h>
#include <Microsoft.Windows.System.Power.PowerManager.g.cpp>
#include <powrprof.h>

namespace winrt::Microsoft::Windows::System::Power::implementation
{
// EnergySaverStatus Functions
EventType& EnergySaverStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_energySaverStatusChangedEvent;
}

void EnergySaverStatus_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterEnergySaverStatusChangedListener(
&PowerManager::EnergySaverStatusChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_energySaverStatusHandle));
}

void EnergySaverStatus_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterEnergySaverStatusChangedListener(
make_self<factory_implementation::PowerManager>()->m_energySaverStatusHandle));
}

void EnergySaverStatus_Update()
{
THROW_IF_FAILED(PowerNotifications_GetEnergySaverStatus(
&make_self<factory_implementation::PowerManager>()->m_cachedEnergySaverStatus));
}

// BatteryStatus Functions
EventType& BatteryStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_batteryStatusChangedEvent;
}

void BatteryStatus_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterCompositeBatteryStatusChangedListener(
&PowerManager::CompositeBatteryStatusChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_batteryStatusHandle));
}

void BatteryStatus_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterCompositeBatteryStatusChangedListener(
make_self<factory_implementation::PowerManager>()->m_batteryStatusHandle));
}

void BatteryStatus_Update()
{
auto status{ &make_self<factory_implementation::PowerManager>()->m_cachedCompositeBatteryStatus };
if (SUCCEEDED(PowerNotifications_GetCompositeBatteryStatus(status)))
{
make_self<factory_implementation::PowerManager>()->ProcessCompositeBatteryStatus(*status);
}
}

// PowerSupplyStatus Functions
EventType& PowerSupplyStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_powerSupplyStatusChangedEvent;
}

void PowerSupplyStatus_Register()
{
BatteryStatus_Register();
}

void PowerSupplyStatus_Unregister()
{
BatteryStatus_Unregister();
}

void PowerSupplyStatus_Update()
{
BatteryStatus_Update();
}

// RemainingChargePercent Functions
EventType& RemainingChargePercent_Event()
{
return make_self<factory_implementation::PowerManager>()->m_remainingChargePercentChangedEvent;
}

void RemainingChargePercent_Register()
{
BatteryStatus_Register();
}

void RemainingChargePercent_Unregister()
{
BatteryStatus_Unregister();
}

void RemainingChargePercent_Update()
{
BatteryStatus_Update();
}

// RemainingDischargeTime Functions
EventType& RemainingDischargeTime_Event()
{
return make_self<factory_implementation::PowerManager>()->m_remainingDischargeTimeChangedEvent;
}

void RemainingDischargeTime_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterDischargeTimeChangedListener(
&PowerManager::RemainingDischargeTimeChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_dischargeTimeHandle));
}

void RemainingDischargeTime_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterDischargeTimeChangedListener(
make_self<factory_implementation::PowerManager>()->m_dischargeTimeHandle));
}

void RemainingDischargeTime_Update()
{
THROW_IF_FAILED(PowerNotifications_GetDischargeTime(
&make_self<factory_implementation::PowerManager>()->m_cachedDischargeTime));
}

// PowerSourceKind Functions
EventType& PowerSourceKind_Event()
{
return make_self<factory_implementation::PowerManager>()->m_powerSourceKindChangedEvent;
}

void PowerSourceKind_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterPowerConditionChangedListener(
&PowerManager::PowerSourceKindChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_powerSourceKindHandle));
}

void PowerSourceKind_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterPowerConditionChangedListener(
make_self<factory_implementation::PowerManager>()->m_powerSourceKindHandle));
}

void PowerSourceKind_Update()
{
THROW_IF_FAILED(PowerNotifications_GetPowerCondition(
&make_self<factory_implementation::PowerManager>()->m_cachedPowerSourceKind));
}

// DisplayStatus Functions
EventType& DisplayStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_displayStatusChangedEvent;
}

void DisplayStatus_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterDisplayStatusChangedListener(
&PowerManager::DisplayStatusChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_displayStatusHandle));
}

void DisplayStatus_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterDisplayStatusChangedListener
(make_self<factory_implementation::PowerManager>()->m_displayStatusHandle));
}

void DisplayStatus_Update()
{
THROW_IF_FAILED(PowerNotifications_GetDisplayStatus(
&make_self<factory_implementation::PowerManager>()->m_cachedDisplayStatus));
}

// SystemIdleStatus Functions
EventType& SystemIdleStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_systemIdleStatusChangedEvent;
}

void SystemIdleStatus_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterSystemIdleStatusChangedListener(
&PowerManager::SystemIdleStatusChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_systemIdleStatusHandle));
}

void SystemIdleStatus_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterSystemIdleStatusChangedListener(
make_self<factory_implementation::PowerManager>()->m_systemIdleStatusHandle));
}

ULONG GetEffectivePowerModeVersion()
{
// We check for the version supported by checking if the feature is supported
// Using NULL as an indicator for uninitialized cache value
auto& version{ make_self<factory_implementation::PowerManager>()->m_powerModeVersion };
if (!version)
{
void* handle{};
auto hr{ PowerRegisterForEffectivePowerModeNotifications(
EFFECTIVE_POWER_MODE_V2, [](EFFECTIVE_POWER_MODE, void*) {}, nullptr, &handle) };
version = SUCCEEDED(hr) ? EFFECTIVE_POWER_MODE_V2 : EFFECTIVE_POWER_MODE_V1;
THROW_IF_FAILED(PowerUnregisterFromEffectivePowerModeNotifications(handle));
}
return version;
}

EventType& EffectivePowerMode_Event()
{
return make_self<factory_implementation::PowerManager>()->m_powerModeChangedEvent;
}

void EffectivePowerMode_Register()
{
ULONG version{ GetEffectivePowerModeVersion() };
auto& powerModeHandle{ make_self<factory_implementation::PowerManager>()->m_powerModeHandle };
THROW_IF_FAILED(PowerRegisterForEffectivePowerModeNotifications(
version, [](EFFECTIVE_POWER_MODE mode, void*)
{
PowerManager::EffectivePowerModeChanged_Callback(mode);
}, nullptr, &powerModeHandle));
}

void EffectivePowerMode_Unregister()
{
auto& powerModeHandle{ make_self<factory_implementation::PowerManager>()->m_powerModeHandle };
THROW_IF_FAILED(PowerUnregisterFromEffectivePowerModeNotifications(powerModeHandle));
powerModeHandle = nullptr;
}

void EffectivePowerMode_Update()
{
// Effectively the Get() for PowerMode
// Needs to get a temporary subscription to get most recent value

struct notify_callback {
EFFECTIVE_POWER_MODE mode;
wil::slim_event done;
} context;

auto handler{ [](EFFECTIVE_POWER_MODE mode, void* rawContext) {
auto context{ reinterpret_cast<notify_callback*>(rawContext) };
context->mode = mode;
context->done.SetEvent();
} };

void* handle{};
ULONG version{ GetEffectivePowerModeVersion() };

THROW_IF_FAILED(PowerRegisterForEffectivePowerModeNotifications(version, handler, &context, &handle));
context.done.wait();
make_self<factory_implementation::PowerManager>()->m_cachedPowerMode = context.mode;
THROW_IF_FAILED(PowerUnregisterFromEffectivePowerModeNotifications(handle));
}

// UserPresenceStatus Functions
EventType& UserPresenceStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_userPresenceStatusChangedEvent;
}

void UserPresenceStatus_Register()
{
THROW_IF_FAILED(PowerNotifications_RegisterUserPresenceStatusChangedListener(
&PowerManager::UserPresenceStatusChanged_Callback,
&make_self<factory_implementation::PowerManager>()->m_userPresenceStatusHandle));
}

void UserPresenceStatus_Unregister()
{
THROW_IF_FAILED(PowerNotifications_UnregisterUserPresenceStatusChangedListener(
make_self<factory_implementation::PowerManager>()->m_userPresenceStatusHandle));
}

void UserPresenceStatus_Update()
{
THROW_IF_FAILED(PowerNotifications_GetUserPresenceStatus(
&make_self<factory_implementation::PowerManager>()->m_cachedUserPresenceStatus));
}

// SystemSuspendStatus Functions
EventType& SystemSuspendStatus_Event()
{
return make_self<factory_implementation::PowerManager>()->m_systemSuspendStatusChangedEvent;
}

ULONG SuspendResumeCallback(void* context, ULONG powerEvent, void* setting)
{
UNREFERENCED_PARAMETER(context);
UNREFERENCED_PARAMETER(setting);
make_self<factory_implementation::PowerManager>()->SystemSuspendStatusChanged_Callback(powerEvent);
return ERROR_SUCCESS;
}

void SystemSuspendStatus_Register()
{
DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS powerParams { 0 };
powerParams.Callback = SuspendResumeCallback;

check_win32(PowerRegisterSuspendResumeNotification(
DEVICE_NOTIFY_CALLBACK,
&powerParams,
&make_self<factory_implementation::PowerManager>()->m_systemSuspendHandle));
}

void SystemSuspendStatus_Unregister()
{
check_win32(PowerUnregisterSuspendResumeNotification(
make_self<factory_implementation::PowerManager>()->m_systemSuspendHandle));
}
}
Loading