reactos/win32ss/user/ntuser/power.h
George Bișoc 181b666fc4
[NTUSER] Stubplement the Win32 power manager
In order for the NT power manager to interact with the Win32 subsystem (thus the whole rest of the system), the Win32 kernel-mode subsystem provides a mechanism that communicates with the kernel power manager via power callouts (aka power requests as per Windows' PDB symbols).
Such mechanism enters in action as soon as Win32 callout routines are estabilished with the PsEstablishWin32Callouts() function.

The NT power manager, the power policy manager respectively, invokes a power callout to denote an exceptional phenomena as a result of power policies or capabilities changes, turning ON/OFF the display, a system time change has occurred, etc.
Such scenarios are described as power events of which the NT power manager sends a WIN32_POWEREVENT_PARAMETERS packet to Win32k via the estabilished "PowerEventCallout" pointer function callout.
For other callouts that inform the Win32 subsystem of impeding power state changes across the system or devices, these are sent as WIN32_POWERSTATE_PARAMETERS packets with its own separate callout.

The purpose of such mechanism is to give Win32k the opportunity to do power related tasks and alert every application of such power events in accordance with what it gets notified by the NT power manager.
Currently this patch stubplements this mechanism in ROS, it is only just the barebones for now. The development of the Win32 power manager will go in parallel with the kernel power manager development (expand, improve, fix the code of issues that whatever may arise).
So far only the PsW32SystemTime power event is implemented for the moment being. This work was decoupled from PR #5719 to avoid clobbering it too much.

=== TODO ===

- Implement power states management communication with the kernel power manager
- Implement the rest of the power events in IntHandlePowerEventWorker
- Implement power event handling in CSRSS (or WinSrv?) which handles any of the events that could not be handled by Win32k otherwise
- Estabilish the power state callout in PsEstablishWin32Callouts() (currently there is no a pointer function that gets assigned to such callout)

CORE-18969
2024-07-13 11:30:19 +02:00

106 lines
2.3 KiB
C

/*
* PROJECT: ReactOS Win32k subsystem
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Power management of the Win32 kernel-mode subsystem
* COPYRIGHT: Copyright 2024 George Bișoc <george.bisoc@reactos.org>
*/
#pragma once
//
// Power Callout type enumeration
//
typedef enum tagPOWER_CALLOUT_TYPE
{
POWER_CALLOUT_EVENT = 0,
POWER_CALLOUT_STATE
} POWER_CALLOUT_TYPE;
//
// Power Callout structure
//
typedef struct tagWIN32POWERCALLOUT
{
/* Links the power callout with the global queue list */
LIST_ENTRY Link;
/*
* Set to POWER_CALLOUT_STATE if the upcoming power callout is a power state
* (IntHandlePowerState does that), POWER_CALLOUT_EVENT otherwise
*/
POWER_CALLOUT_TYPE Type;
/* The captured Win32 power event parameters (the params are set to none if Type == POWER_STATE) */
WIN32_POWEREVENT_PARAMETERS Params;
} WIN32POWERCALLOUT, *PWIN32POWERCALLOUT;
//
// Ensures the power callout mutex lock is acquired
//
#define ASSERT_POWER_CALLOUT_LOCK_ACQUIRED() \
ASSERT(gpPowerCalloutMutexOwnerThread == KeGetCurrentThread())
//
// Power Manager data
//
extern LIST_ENTRY gPowerCalloutsQueueList;
extern PFAST_MUTEX gpPowerCalloutMutexLock;
extern PKEVENT gpPowerRequestCalloutEvent;
extern PKTHREAD gpPowerCalloutMutexOwnerThread;
//
// Function prototypes
//
NTSTATUS
NTAPI
IntInitWin32PowerManagement(
_In_ HANDLE hPowerRequestEvent);
NTSTATUS
NTAPI
IntWin32PowerManagementCleanup(VOID);
NTSTATUS
NTAPI
IntHandlePowerEvent(
_In_ PWIN32_POWEREVENT_PARAMETERS pWin32PwrEventParams);
NTSTATUS
NTAPI
IntHandlePowerState(
_In_ PWIN32_POWERSTATE_PARAMETERS pWin32PwrStateParams);
//
// Power Callout locking mechanism
//
FORCEINLINE
VOID
IntAcquirePowerCalloutLock(VOID)
{
KeEnterCriticalRegion();
ExAcquireFastMutexUnsafe(gpPowerCalloutMutexLock);
gpPowerCalloutMutexOwnerThread = KeGetCurrentThread();
}
FORCEINLINE
VOID
IntReleasePowerCalloutLock(VOID)
{
ExReleaseFastMutexUnsafe(gpPowerCalloutMutexLock);
gpPowerCalloutMutexOwnerThread = NULL;
KeLeaveCriticalRegion();
}
//
// Checks if the following thread is a Win32 thread
//
FORCEINLINE
BOOL
IntIsThreadWin32Thread(
_In_ PETHREAD Thread)
{
return (Thread->Tcb.Win32Thread != NULL) ? TRUE : FALSE;
}
/* EOF */