user: Make ExitWindowsEx asynchronous by deferring the real work to the explorer process.
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 70ec9fc..743bded 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -411,6 +411,18 @@
 {
     TRACE("(%x,%lx)\n", flags, reason);
 
+    if (!WIN_IsCurrentThread( GetDesktopWindow() ))
+    {
+        BOOL ret = PostMessageW( GetDesktopWindow(), WM_USER + 666,
+                                 MAKEWPARAM( flags, 0xbabe ), reason);
+        if (ret)
+            return TRUE;
+        /* this can happen if explorer hasn't been started or created the
+         * desktop window yet */
+        WARN("PostMessage failed with error %ld\n", GetLastError());
+        /* fall through to doing it in the same process */
+    }
+
     if ((flags & EWX_FORCE) == 0)
     {
         HWND *list;
@@ -468,6 +480,5 @@
             MESSAGE("wine: Failed to start wineboot\n");
     }
 
-    ExitProcess(0);
     return TRUE;
 }
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index 67025b8..d4db46d 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -62,6 +62,13 @@
         }
         return 0;
 
+    /* simple check to prevent applications accidentally triggering the
+     * ExitWindowsEx code if they send random messages to the desktop window */
+    case WM_USER + 666:
+        if (HIWORD(wp) == 0xbabe)
+            return ExitWindowsEx( LOWORD(wp), lp );
+        return DefWindowProcW( hwnd, message, wp, lp );
+
     default:
         return DefWindowProcW( hwnd, message, wp, lp );
     }