summaryrefslogtreecommitdiff
path: root/src/eggsmclient-win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/eggsmclient-win32.c')
-rw-r--r--src/eggsmclient-win32.c356
1 files changed, 0 insertions, 356 deletions
diff --git a/src/eggsmclient-win32.c b/src/eggsmclient-win32.c
deleted file mode 100644
index c037a15..0000000
--- a/src/eggsmclient-win32.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (C) 2007 Novell, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 3 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library 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.
- */
-
-/* EggSMClientWin32
- *
- * For details on the Windows XP logout process, see:
- * http://msdn.microsoft.com/en-us/library/aa376876.aspx.
- *
- * Vista adds some new APIs which EggSMClient does not make use of; see
- * http://msdn.microsoft.com/en-us/library/ms700677(VS.85).aspx
- *
- * When shutting down, Windows sends every top-level window a
- * WM_QUERYENDSESSION event, which the application must respond to
- * synchronously, saying whether or not it will quit. To avoid main
- * loop re-entrancy problems (and to avoid having to muck about too
- * much with the guts of the gdk-win32 main loop), we watch for this
- * event in a separate thread, which then signals the main thread and
- * waits for the main thread to handle the event. Since we don't want
- * to require g_thread_init() to be called, we do this all using
- * Windows-specific thread methods.
- *
- * After the application handles the WM_QUERYENDSESSION event,
- * Windows then sends it a WM_ENDSESSION event with a TRUE or FALSE
- * parameter indicating whether the session is or is not actually
- * going to end now. We handle this from the other thread as well.
- *
- * As mentioned above, Vista introduces several additional new APIs
- * that don't fit into the (current) EggSMClient API. Windows also has
- * an entirely separate shutdown-notification scheme for non-GUI apps,
- * which we also don't handle here.
- */
-
-#include "config.h"
-
-#include "eggsmclient-private.h"
-#include <gdk/gdk.h>
-
-#define WIN32_LEAN_AND_MEAN
-#define UNICODE
-#include <windows.h>
-#include <process.h>
-
-#define EGG_TYPE_SM_CLIENT_WIN32 (egg_sm_client_win32_get_type ())
-#define EGG_SM_CLIENT_WIN32(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32))
-#define EGG_SM_CLIENT_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
-#define EGG_IS_SM_CLIENT_WIN32(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_WIN32))
-#define EGG_IS_SM_CLIENT_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_WIN32))
-#define EGG_SM_CLIENT_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_WIN32, EggSMClientWin32Class))
-
-typedef struct _EggSMClientWin32 EggSMClientWin32;
-typedef struct _EggSMClientWin32Class EggSMClientWin32Class;
-
-struct _EggSMClientWin32
-{
- EggSMClient parent;
-
- HANDLE message_event, response_event;
-
- volatile GSourceFunc event;
- volatile gboolean will_quit;
-};
-
-struct _EggSMClientWin32Class
-{
- EggSMClientClass parent_class;
-
-};
-
-static void sm_client_win32_startup (EggSMClient *client,
- const char *client_id);
-static void sm_client_win32_will_quit (EggSMClient *client,
- gboolean will_quit);
-static gboolean sm_client_win32_end_session (EggSMClient *client,
- EggSMClientEndStyle style,
- gboolean request_confirmation);
-
-static GSource *g_win32_handle_source_add (HANDLE handle, GSourceFunc callback,
- gpointer user_data);
-static gboolean got_message (gpointer user_data);
-static void sm_client_thread (gpointer data);
-
-G_DEFINE_TYPE (EggSMClientWin32, egg_sm_client_win32, EGG_TYPE_SM_CLIENT)
-
-static void
-egg_sm_client_win32_init (EggSMClientWin32 *win32)
-{
- ;
-}
-
-static void
-egg_sm_client_win32_class_init (EggSMClientWin32Class *klass)
-{
- EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
-
- sm_client_class->startup = sm_client_win32_startup;
- sm_client_class->will_quit = sm_client_win32_will_quit;
- sm_client_class->end_session = sm_client_win32_end_session;
-}
-
-EggSMClient *
-egg_sm_client_win32_new (void)
-{
- return g_object_new (EGG_TYPE_SM_CLIENT_WIN32, NULL);
-}
-
-static void
-sm_client_win32_startup (EggSMClient *client,
- const char *client_id)
-{
- EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
-
- win32->message_event = CreateEvent (NULL, FALSE, FALSE, NULL);
- win32->response_event = CreateEvent (NULL, FALSE, FALSE, NULL);
- g_win32_handle_source_add (win32->message_event, got_message, win32);
- _beginthread (sm_client_thread, 0, client);
-}
-
-static void
-sm_client_win32_will_quit (EggSMClient *client,
- gboolean will_quit)
-{
- EggSMClientWin32 *win32 = (EggSMClientWin32 *)client;
-
- win32->will_quit = will_quit;
- SetEvent (win32->response_event);
-}
-
-static gboolean
-sm_client_win32_end_session (EggSMClient *client,
- EggSMClientEndStyle style,
- gboolean request_confirmation)
-{
- UINT uFlags = EWX_LOGOFF;
-
- switch (style)
- {
- case EGG_SM_CLIENT_END_SESSION_DEFAULT:
- case EGG_SM_CLIENT_LOGOUT:
- uFlags = EWX_LOGOFF;
- break;
- case EGG_SM_CLIENT_REBOOT:
- uFlags = EWX_REBOOT;
- break;
- case EGG_SM_CLIENT_SHUTDOWN:
- uFlags = EWX_POWEROFF;
- break;
- }
-
- /* There's no way to make ExitWindowsEx() show a logout dialog, so
- * we ignore @request_confirmation.
- */
-
-#ifdef SHTDN_REASON_FLAG_PLANNED
- ExitWindowsEx (uFlags, SHTDN_REASON_FLAG_PLANNED);
-#else
- ExitWindowsEx (uFlags, 0);
-#endif
-
- return TRUE;
-}
-
-
-/* callbacks from logout-listener thread */
-
-static gboolean
-emit_quit_requested (gpointer smclient)
-{
- gdk_threads_enter ();
- egg_sm_client_quit_requested (smclient);
- gdk_threads_leave ();
-
- return FALSE;
-}
-
-static gboolean
-emit_quit (gpointer smclient)
-{
- EggSMClientWin32 *win32 = smclient;
-
- gdk_threads_enter ();
- egg_sm_client_quit (smclient);
- gdk_threads_leave ();
-
- SetEvent (win32->response_event);
- return FALSE;
-}
-
-static gboolean
-emit_quit_cancelled (gpointer smclient)
-{
- EggSMClientWin32 *win32 = smclient;
-
- gdk_threads_enter ();
- egg_sm_client_quit_cancelled (smclient);
- gdk_threads_leave ();
-
- SetEvent (win32->response_event);
- return FALSE;
-}
-
-static gboolean
-got_message (gpointer smclient)
-{
- EggSMClientWin32 *win32 = smclient;
-
- win32->event (win32);
- return TRUE;
-}
-
-/* Windows HANDLE GSource */
-
-typedef struct
-{
- GSource source;
- GPollFD pollfd;
-} GWin32HandleSource;
-
-static gboolean
-g_win32_handle_source_prepare (GSource *source, gint *timeout)
-{
- *timeout = -1;
- return FALSE;
-}
-
-static gboolean
-g_win32_handle_source_check (GSource *source)
-{
- GWin32HandleSource *hsource = (GWin32HandleSource *)source;
-
- return hsource->pollfd.revents;
-}
-
-static gboolean
-g_win32_handle_source_dispatch (GSource *source, GSourceFunc callback, gpointer user_data)
-{
- return (*callback) (user_data);
-}
-
-static void
-g_win32_handle_source_finalize (GSource *source)
-{
- ;
-}
-
-GSourceFuncs g_win32_handle_source_funcs =
-{
- g_win32_handle_source_prepare,
- g_win32_handle_source_check,
- g_win32_handle_source_dispatch,
- g_win32_handle_source_finalize
-};
-
-static GSource *
-g_win32_handle_source_add (HANDLE handle, GSourceFunc callback, gpointer user_data)
-{
- GWin32HandleSource *hsource;
- GSource *source;
-
- source = g_source_new (&g_win32_handle_source_funcs, sizeof (GWin32HandleSource));
- hsource = (GWin32HandleSource *)source;
- hsource->pollfd.fd = (int)handle;
- hsource->pollfd.events = G_IO_IN;
- hsource->pollfd.revents = 0;
- g_source_add_poll (source, &hsource->pollfd);
-
- g_source_set_callback (source, callback, user_data, NULL);
- g_source_attach (source, NULL);
- return source;
-}
-
-/* logout-listener thread */
-
-LRESULT CALLBACK
-sm_client_win32_window_procedure (HWND hwnd,
- UINT message,
- WPARAM wParam,
- LPARAM lParam)
-{
- EggSMClientWin32 *win32 =
- (EggSMClientWin32 *)GetWindowLongPtr (hwnd, GWLP_USERDATA);
-
- switch (message)
- {
- case WM_QUERYENDSESSION:
- win32->event = emit_quit_requested;
- SetEvent (win32->message_event);
-
- WaitForSingleObject (win32->response_event, INFINITE);
- return win32->will_quit;
-
- case WM_ENDSESSION:
- if (wParam)
- {
- /* The session is ending */
- win32->event = emit_quit;
- }
- else
- {
- /* Nope, the session *isn't* ending */
- win32->event = emit_quit_cancelled;
- }
-
- SetEvent (win32->message_event);
- WaitForSingleObject (win32->response_event, INFINITE);
-
- return 0;
-
- default:
- return DefWindowProc (hwnd, message, wParam, lParam);
- }
-}
-
-static void
-sm_client_thread (gpointer smclient)
-{
- HINSTANCE instance;
- WNDCLASSEXW wcl;
- ATOM klass;
- HWND window;
- MSG msg;
-
- instance = GetModuleHandle (NULL);
-
- memset (&wcl, 0, sizeof (WNDCLASSEX));
- wcl.cbSize = sizeof (WNDCLASSEX);
- wcl.lpfnWndProc = sm_client_win32_window_procedure;
- wcl.hInstance = instance;
- wcl.lpszClassName = L"EggSmClientWindow";
- klass = RegisterClassEx (&wcl);
-
- window = CreateWindowEx (0, MAKEINTRESOURCE (klass),
- L"EggSmClientWindow", 0,
- 10, 10, 50, 50, GetDesktopWindow (),
- NULL, instance, NULL);
- SetWindowLongPtr (window, GWLP_USERDATA, (LONG_PTR)smclient);
-
- /* main loop */
- while (GetMessage (&msg, NULL, 0, 0))
- DispatchMessage (&msg);
-}