[PATCH 3/5] server: Add server requests for managing the system execution state.
Chip Davis
cdavis at codeweavers.com
Tue Aug 13 11:50:09 CDT 2019
Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---
include/winnt.h | 1 +
server/Makefile.in | 1 +
server/power.c | 241 ++++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 33 ++++++
4 files changed, 276 insertions(+)
create mode 100644 server/power.c
diff --git a/include/winnt.h b/include/winnt.h
index 87b4adbfea0..e94ca65f0aa 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -906,6 +906,7 @@ typedef enum _HEAP_INFORMATION_CLASS {
#define ES_SYSTEM_REQUIRED 0x00000001
#define ES_DISPLAY_REQUIRED 0x00000002
#define ES_USER_PRESENT 0x00000004
+#define ES_AWAYMODE_REQUIRED 0x00000040
#define ES_CONTINUOUS 0x80000000
/* The Win32 register context */
diff --git a/server/Makefile.in b/server/Makefile.in
index b39bd30305b..e619d8223fb 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -27,6 +27,7 @@ C_SRCS = \
procfs.c \
ptrace.c \
queue.c \
+ power.c \
region.c \
registry.c \
request.c \
diff --git a/server/power.c b/server/power.c
new file mode 100644
index 00000000000..4ac35589182
--- /dev/null
+++ b/server/power.c
@@ -0,0 +1,241 @@
+/*
+ * Power management support
+ *
+ * Copyright (C) 1998 Alexandre Julliard
+ * Copyright (C) 2003 Mike McCormack
+ * Copyright (C) 2005 Robert Shearman
+ * Copyright (C) 2019 Chip Davis for CodeWeavers
+ *
+ * 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 "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+
+#include "handle.h"
+#include "request.h"
+#include "unicode.h"
+
+static unsigned int sys_count = 0; /* number of holds on system sleep */
+static unsigned int disp_count = 0; /* number of holds on display sleep */
+static unsigned int away_count = 0; /* number of away mode requests */
+
+struct power_request
+{
+ struct object obj; /* object header */
+ struct unicode_str reason; /* stated reason for the request */
+ unsigned sys : 1; /* hold system sleep? */
+ unsigned disp : 1; /* hold display sleep? */
+ unsigned away : 1; /* request away mode? */
+};
+
+static void power_request_dump( struct object *obj, int verbose );
+static struct object_type *power_request_get_type( struct object *obj );
+static void power_request_destroy( struct object *obj );
+
+static const struct object_ops power_request_ops =
+{
+ sizeof(struct power_request), /* size */
+ power_request_dump, /* dump */
+ power_request_get_type, /* get_type */
+ no_add_queue, /* add_queue */
+ NULL, /* remove_queue */
+ NULL, /* signaled */
+ NULL, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ no_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ no_lookup_name, /* lookup_name */
+ no_link_name, /* link_name */
+ NULL, /* unlink_name */
+ no_open_file, /* open_file */
+ no_kernel_obj_list, /* get_kernel_obj_list */
+ no_close_handle, /* close_handle */
+ power_request_destroy /* destroy */
+};
+
+static void power_request_dump( struct object *obj, int verbose )
+{
+ struct power_request *power_req = (struct power_request *)obj;
+ assert( obj->ops == &power_request_ops );
+ fprintf( stderr, "PowerRequest reason=" );
+ dump_strW( power_req->reason.str, power_req->reason.len, stderr, "\"\"" );
+ fprintf( stderr, " hold system=%s hold display=%s away mode=%s\n", power_req->sys ? "TRUE" : "FALSE",
+ power_req->disp ? "TRUE" : "FALSE", power_req->away ? "TRUE" : "FALSE" );
+}
+
+static struct object_type *power_request_get_type( struct object *obj )
+{
+ static const WCHAR name[] = {'P', 'o', 'w', 'e', 'r', 'R', 'e', 'q', 'u', 'e', 's', 't'};
+ static const struct unicode_str str = { name, sizeof(name) };
+ return get_object_type( &str );
+}
+
+static void set_power_request( struct power_request *power_req, POWER_REQUEST_TYPE type )
+{
+ switch (type)
+ {
+ case PowerRequestDisplayRequired:
+ if (!power_req->disp)
+ ++disp_count;
+ power_req->disp = TRUE;
+ break;
+ case PowerRequestSystemRequired:
+ if (!power_req->sys)
+ ++sys_count;
+ power_req->sys = TRUE;
+ break;
+ case PowerRequestAwayModeRequired:
+ if (!power_req->away)
+ ++away_count;
+ power_req->away = TRUE;
+ break;
+ }
+}
+
+static void clear_power_request( struct power_request *power_req, POWER_REQUEST_TYPE type )
+{
+ switch (type)
+ {
+ case PowerRequestDisplayRequired:
+ if (power_req->disp)
+ --disp_count;
+ power_req->disp = FALSE;
+ break;
+ case PowerRequestSystemRequired:
+ if (power_req->sys)
+ --sys_count;
+ power_req->sys = FALSE;
+ break;
+ case PowerRequestAwayModeRequired:
+ if (power_req->away)
+ --away_count;
+ power_req->away = FALSE;
+ break;
+ }
+}
+
+static void power_request_destroy( struct object *obj )
+{
+ struct power_request *power_req;
+
+ assert( obj->ops == &power_request_ops );
+ power_req = (struct power_request *)obj;
+
+ clear_power_request( power_req, PowerRequestDisplayRequired );
+ clear_power_request( power_req, PowerRequestSystemRequired );
+ clear_power_request( power_req, PowerRequestAwayModeRequired );
+
+ free( (void *)power_req->reason.str );
+}
+
+/* creates a new power request */
+static struct power_request *create_power_request( struct unicode_str *reason )
+{
+ struct power_request *power_req = alloc_object( &power_request_ops );
+ if (power_req)
+ {
+ power_req->reason.str = memdup(reason->str, reason->len * sizeof(WCHAR));
+ power_req->reason.len = reason->len;
+ power_req->sys = 0;
+ power_req->disp = 0;
+ power_req->away = 0;
+ }
+ return power_req;
+}
+
+static struct power_request *get_power_request_obj( struct process *process, obj_handle_t handle )
+{
+ return (struct power_request *)get_handle_obj( process, handle, 0, &power_request_ops );
+}
+
+
+/* Get the current system execution state */
+DECL_HANDLER(get_system_execution_state)
+{
+ reply->exec_state = 0;
+ if (sys_count != 0)
+ reply->exec_state |= ES_SYSTEM_REQUIRED;
+ if (disp_count != 0)
+ reply->exec_state |= ES_DISPLAY_REQUIRED;
+ if (away_count != 0)
+ reply->exec_state |= ES_AWAYMODE_REQUIRED;
+}
+
+/* Increment the current system execution state */
+DECL_HANDLER(change_system_execution_state)
+{
+ if ((req->old_state & ES_SYSTEM_REQUIRED) && !(req->new_state & ES_SYSTEM_REQUIRED))
+ --sys_count;
+ else if (!(req->old_state & ES_SYSTEM_REQUIRED) && (req->new_state & ES_SYSTEM_REQUIRED))
+ ++sys_count;
+
+ if ((req->old_state & ES_DISPLAY_REQUIRED) && !(req->new_state & ES_DISPLAY_REQUIRED))
+ --disp_count;
+ else if (!(req->old_state & ES_DISPLAY_REQUIRED) && (req->new_state & ES_DISPLAY_REQUIRED))
+ ++disp_count;
+
+ if ((req->old_state & ES_AWAYMODE_REQUIRED) && !(req->new_state & ES_AWAYMODE_REQUIRED))
+ --away_count;
+ else if (!(req->old_state & ES_AWAYMODE_REQUIRED) && (req->new_state & ES_AWAYMODE_REQUIRED))
+ ++away_count;
+}
+
+/* Create a power request object */
+DECL_HANDLER(create_power_request)
+{
+ struct unicode_str reason = get_req_unicode_str();
+
+ struct power_request *power_req = create_power_request( &reason );
+
+ if (power_req)
+ {
+ reply->handle = alloc_handle_no_access_check( current->process, power_req, 0, 0 );
+ release_object( power_req );
+ }
+ else
+ {
+ set_error( STATUS_NO_MEMORY );
+ }
+}
+
+/* Enable a request on a power request object */
+DECL_HANDLER(set_power_request)
+{
+ struct power_request *power_req = get_power_request_obj( current->process, req->handle );
+
+ if (power_req)
+ set_power_request( power_req, req->request );
+}
+
+/* Disable a request on a power request object */
+DECL_HANDLER(clear_power_request)
+{
+ struct power_request *power_req = get_power_request_obj( current->process, req->handle );
+
+ if (power_req)
+ clear_power_request( power_req, req->request );
+}
+
diff --git a/server/protocol.def b/server/protocol.def
index 8157199f2fa..7dea95e25fb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3944,3 +3944,36 @@ struct handle_info
@REQ(resume_process)
obj_handle_t handle; /* process handle */
@END
+
+/* Get the current system execution state */
+ at REQ(get_system_execution_state)
+ at REPLY
+ unsigned int exec_state; /* current execution state */
+ at END
+
+/* Change the current system execution state */
+ at REQ(change_system_execution_state)
+ unsigned int old_state; /* thread's old execution state */
+ unsigned int new_state; /* thread's new execution state */
+ at END
+
+/* Create a power request object */
+ at REQ(create_power_request)
+ VARARG(reason,unicode_str); /* reason for the request */
+ at REPLY
+ obj_handle_t handle; /* power request handle */
+ at END
+
+/* Enable a request on a power request object */
+ at REQ(set_power_request)
+ obj_handle_t handle; /* power request handle */
+ unsigned int request; /* the request to enable */
+ at END
+
+/* Disable a request on a power request object */
+ at REQ(clear_power_request)
+ obj_handle_t handle; /* power request handle */
+ unsigned int request; /* the request to disable */
+ at END
+
+
--
2.21.0
More information about the wine-devel
mailing list