set most of trunk svn property eol-style:native
[reactos.git] / reactos / base / system / winlogon / screensaver.c
index 197079a..a86c02f 100644 (file)
-/*\r
- * COPYRIGHT:       See COPYING in the top level directory\r
- * PROJECT:         ReactOS kernel\r
- * FILE:            services/winlogon/screensaver.c\r
- * PURPOSE:         Screen saver management\r
- * PROGRAMMERS:     HervĂ© Poussineau (hpoussin@reactos.org)\r
- */\r
-\r
-#include "winlogon.h"\r
-\r
-#define YDEBUG\r
-#include <wine/debug.h>\r
-\r
-#ifndef USE_GETLASTINPUTINFO\r
-static LRESULT CALLBACK\r
-KeyboardActivityProc(\r
-       IN INT nCode,\r
-       IN WPARAM wParam,\r
-       IN LPARAM lParam)\r
-{\r
-       InterlockedExchange((LONG*)&WLSession->LastActivity, ((PKBDLLHOOKSTRUCT)lParam)->time);\r
-       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
-}\r
-\r
-static LRESULT CALLBACK\r
-MouseActivityProc(\r
-       IN INT nCode,\r
-       IN WPARAM wParam,\r
-       IN LPARAM lParam)\r
-{\r
-       InterlockedExchange((LONG*)&WLSession->LastActivity, ((PMSLLHOOKSTRUCT)lParam)->time);\r
-       return CallNextHookEx(NULL, nCode, wParam, lParam);\r
-}\r
-#endif\r
-\r
-static VOID\r
-LoadScreenSaverParameters(\r
-       OUT LPDWORD Timeout)\r
-{\r
-       BOOL Enabled;\r
-\r
-       if (!SystemParametersInfoW(SPI_GETSCREENSAVETIMEOUT, 0, Timeout, 0))\r
-       {\r
-               WARN("WL: Unable to get screen saver timeout (error %lu). Disabling it\n", GetLastError());\r
-               *Timeout = INFINITE;\r
-       }\r
-       else if (!SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, 0, &Enabled, 0))\r
-       {\r
-               WARN("WL: Unable to check if screen saver is enabled (error %lu). Disabling it\n", GetLastError());\r
-               *Timeout = INFINITE;\r
-       }\r
-       else if (!Enabled)\r
-       {\r
-               TRACE("WL: Screen saver is disabled\n");\r
-               *Timeout = INFINITE;\r
-       }\r
-       else\r
-       {\r
-               TRACE("WL: Screen saver timeout: %lu seconds\n", *Timeout);\r
-               *Timeout *= 1000;\r
-       }\r
-}\r
-\r
-static DWORD WINAPI\r
-ScreenSaverThreadMain(\r
-       IN LPVOID lpParameter)\r
-{\r
-       PWLSESSION Session = (PWLSESSION)lpParameter;\r
-       HANDLE HandleArray[3];\r
-#ifdef USE_GETLASTINPUTINFO\r
-       LASTINPUTINFO lastInputInfo;\r
-#else\r
-       DWORD LastActivity;\r
-#endif\r
-       DWORD TimeToWait;\r
-       DWORD Timeout; /* Timeout before screen saver starts, in milliseconds */\r
-       DWORD ret;\r
-\r
-       if (!ImpersonateLoggedOnUser(Session->UserToken))\r
-       {\r
-               ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());\r
-               return 0;\r
-       }\r
-\r
-       Session->hUserActivity = CreateEventW(NULL, FALSE, FALSE, NULL);\r
-       if (!Session->hUserActivity)\r
-       {\r
-               ERR("WL: Unable to create event (error %lu)\n", GetLastError());\r
-               goto cleanup;\r
-       }\r
-\r
-       Session->hEndOfScreenSaver = CreateEventW(NULL, FALSE, FALSE, NULL);\r
-       if (!Session->hEndOfScreenSaver)\r
-       {\r
-               ERR("WL: Unable to create event (error %lu)\n", GetLastError());\r
-               goto cleanup;\r
-       }\r
-\r
-       HandleArray[0] = Session->hEndOfScreenSaverThread;\r
-       HandleArray[1] = Session->hScreenSaverParametersChanged;\r
-       HandleArray[2] = Session->hEndOfScreenSaver;\r
-\r
-       LoadScreenSaverParameters(&Timeout);\r
-\r
-#ifndef USE_GETLASTINPUTINFO\r
-       InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());\r
-#else\r
-       lastInputInfo.cbSize = sizeof(LASTINPUTINFO);\r
-#endif\r
-       for (;;)\r
-       {\r
-               /* See the time of last activity and calculate a timeout */\r
-#ifndef USE_GETLASTINPUTINFO\r
-               LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);\r
-               TimeToWait = Timeout - (GetTickCount() - LastActivity);\r
-#else\r
-               if (GetLastInputInfo(&lastInputInfo))\r
-                       TimeToWait = Timeout - (GetTickCount() - lastInputInfo.dwTime);\r
-               else\r
-               {\r
-                       WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());\r
-                       TimeToWait = 10; /* Try again in 10 ms */\r
-               }\r
-#endif\r
-               if (TimeToWait > Timeout)\r
-               {\r
-                       /* GetTickCount() got back to 0 */\r
-                       TimeToWait = Timeout;\r
-               }\r
-\r
-               /* Wait for the timeout, or the end of this thread */\r
-               ret = WaitForMultipleObjects(2, HandleArray, FALSE, TimeToWait);\r
-               if (ret == WAIT_OBJECT_0)\r
-                       break;\r
-               else if (ret == WAIT_OBJECT_0 + 1)\r
-                       LoadScreenSaverParameters(&Timeout);\r
-\r
-               /* Check if we didn't had recent activity */\r
-#ifndef USE_GETLASTINPUTINFO\r
-               LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);\r
-               if (LastActivity + Timeout > GetTickCount())\r
-                       continue;\r
-#else\r
-               if (!GetLastInputInfo(&lastInputInfo))\r
-               {\r
-                       WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());\r
-                       continue;\r
-               }\r
-               if (lastInputInfo.dwTime + Timeout > GetTickCount())\r
-                       continue;\r
-#endif\r
-\r
-               /* Run screen saver */\r
-               PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_TIMEOUT, 0);\r
-\r
-               /* Wait for the end of this thread or of the screen saver */\r
-               ret = WaitForMultipleObjects(3, HandleArray, FALSE, INFINITE);\r
-               if (ret == WAIT_OBJECT_0)\r
-                       break;\r
-               else if (ret == WAIT_OBJECT_0 + 1)\r
-                       LoadScreenSaverParameters(&Timeout);\r
-               else if (ret == WAIT_OBJECT_0 + 2)\r
-                       SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, FALSE, NULL, 0);\r
-       }\r
-\r
-cleanup:\r
-       RevertToSelf();\r
-       if (Session->hUserActivity)\r
-               CloseHandle(Session->hUserActivity);\r
-       if (Session->hEndOfScreenSaver)\r
-               CloseHandle(Session->hEndOfScreenSaver);\r
-#ifndef USE_GETLASTINPUTINFO\r
-       if (Session->KeyboardHook)\r
-               UnhookWindowsHookEx(Session->KeyboardHook);\r
-       if (Session->MouseHook)\r
-               UnhookWindowsHookEx(Session->MouseHook);\r
-#endif\r
-       CloseHandle(Session->hEndOfScreenSaverThread);\r
-       CloseHandle(Session->hScreenSaverParametersChanged);\r
-       return 0;\r
-}\r
-\r
-BOOL\r
-InitializeScreenSaver(\r
-       IN OUT PWLSESSION Session)\r
-{\r
-       HANDLE ScreenSaverThread;\r
-\r
-#ifndef USE_GETLASTINPUTINFO\r
-       /* Register hooks to detect keyboard and mouse activity */\r
-       Session->KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardActivityProc, hAppInstance, 0);\r
-       if (!Session->KeyboardHook)\r
-       {\r
-               ERR("WL: Unable to register keyboard hook\n");\r
-               return FALSE;\r
-       }\r
-       Session->MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseActivityProc, hAppInstance, 0);\r
-       if (!Session->MouseHook)\r
-       {\r
-               ERR("WL: Unable to register mouse hook\n");\r
-               return FALSE;\r
-       }\r
-#endif\r
-\r
-       Session->hScreenSaverParametersChanged = CreateEventW(NULL, FALSE, FALSE, NULL);\r
-       if (!Session->hScreenSaverParametersChanged)\r
-       {\r
-               WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());\r
-               return TRUE;\r
-       }\r
-       Session->hEndOfScreenSaverThread = CreateEventW(NULL, FALSE, FALSE, NULL);\r
-       if (!Session->hEndOfScreenSaverThread)\r
-       {\r
-               WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());\r
-               CloseHandle(Session->hScreenSaverParametersChanged);\r
-               return TRUE;\r
-       }\r
-\r
-       ScreenSaverThread = CreateThread(\r
-               NULL,\r
-               0,\r
-               ScreenSaverThreadMain,\r
-               Session,\r
-               0,\r
-               NULL);\r
-       if (ScreenSaverThread)\r
-               CloseHandle(ScreenSaverThread);\r
-       else\r
-               WARN("WL: Unable to start screen saver thread\n");\r
-\r
-       return TRUE;\r
-}\r
-\r
-VOID\r
-StartScreenSaver(\r
-       IN PWLSESSION Session)\r
-{\r
-       HKEY hKey = NULL;\r
-       WCHAR szApplicationName[MAX_PATH];\r
-       WCHAR szCommandLine[MAX_PATH + 3];\r
-       DWORD bufferSize = sizeof(szApplicationName)- 1;\r
-       DWORD dwType;\r
-       STARTUPINFOW StartupInfo;\r
-       PROCESS_INFORMATION ProcessInformation;\r
-       HANDLE HandleArray[2];\r
-       LONG rc;\r
-       DWORD Status;\r
-       BOOL ret = FALSE;\r
-\r
-       if (!ImpersonateLoggedOnUser(Session->UserToken))\r
-       {\r
-               ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());\r
-               goto cleanup;\r
-       }\r
-\r
-       rc = RegOpenKeyExW(\r
-               HKEY_CURRENT_USER,\r
-               L"Control Panel\\Desktop",\r
-               0,\r
-               KEY_QUERY_VALUE,\r
-               &hKey);\r
-       if (rc != ERROR_SUCCESS)\r
-               goto cleanup;\r
-\r
-       szApplicationName[bufferSize] = 0; /* Terminate the string */\r
-       rc = RegQueryValueExW(\r
-               hKey,\r
-               L"SCRNSAVE.EXE",\r
-               0,\r
-               &dwType,\r
-               (LPBYTE)szApplicationName,\r
-               &bufferSize);\r
-       if (rc != ERROR_SUCCESS || dwType != REG_SZ)\r
-               goto cleanup;\r
-\r
-       wsprintfW(szCommandLine, L"%s /s", szApplicationName);\r
-       TRACE("WL: Executing %S\n", szCommandLine);\r
-\r
-       ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));\r
-       ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));\r
-       StartupInfo.cb = sizeof(STARTUPINFOW);\r
-       /* FIXME: run the screen saver on the screen saver desktop */\r
-       ret = CreateProcessW(\r
-               szApplicationName,\r
-               szCommandLine,\r
-               NULL,\r
-               NULL,\r
-               FALSE,\r
-               0,\r
-               NULL,\r
-               NULL,\r
-               &StartupInfo,\r
-               &ProcessInformation);\r
-       if (!ret)\r
-       {\r
-               WARN("WL: Unable to start %S, error %lu\n", szApplicationName, GetLastError());\r
-               goto cleanup;\r
-       }\r
-       CloseHandle(ProcessInformation.hThread);\r
-\r
-       SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0);\r
-\r
-       /* Wait the end of the process or some other activity */\r
-       ResetEvent(Session->hUserActivity);\r
-       HandleArray[0] = ProcessInformation.hProcess;\r
-       HandleArray[1] = Session->hUserActivity;\r
-       Status = WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE);\r
-       if (Status == WAIT_OBJECT_0 + 1)\r
-       {\r
-               /* Kill the screen saver */\r
-               TerminateProcess(ProcessInformation.hProcess, 0);\r
-       }\r
-       SetEvent(Session->hEndOfScreenSaver);\r
-\r
-       CloseHandle(ProcessInformation.hProcess);\r
-\r
-cleanup:\r
-       RevertToSelf();\r
-       if (hKey)\r
-               RegCloseKey(hKey);\r
-       if (!ret)\r
-       {\r
-               PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_ACTIVITY, 0);\r
-#ifndef USE_GETLASTINPUTINFO\r
-               InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());\r
-#endif\r
-       }\r
-}\r
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            services/winlogon/screensaver.c
+ * PURPOSE:         Screen saver management
+ * PROGRAMMERS:     HervĂ© Poussineau (hpoussin@reactos.org)
+ */
+
+#include "winlogon.h"
+
+#define YDEBUG
+#include <wine/debug.h>
+
+#ifndef USE_GETLASTINPUTINFO
+static LRESULT CALLBACK
+KeyboardActivityProc(
+       IN INT nCode,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
+{
+       InterlockedExchange((LONG*)&WLSession->LastActivity, ((PKBDLLHOOKSTRUCT)lParam)->time);
+       return CallNextHookEx(NULL, nCode, wParam, lParam);
+}
+
+static LRESULT CALLBACK
+MouseActivityProc(
+       IN INT nCode,
+       IN WPARAM wParam,
+       IN LPARAM lParam)
+{
+       InterlockedExchange((LONG*)&WLSession->LastActivity, ((PMSLLHOOKSTRUCT)lParam)->time);
+       return CallNextHookEx(NULL, nCode, wParam, lParam);
+}
+#endif
+
+static VOID
+LoadScreenSaverParameters(
+       OUT LPDWORD Timeout)
+{
+       BOOL Enabled;
+
+       if (!SystemParametersInfoW(SPI_GETSCREENSAVETIMEOUT, 0, Timeout, 0))
+       {
+               WARN("WL: Unable to get screen saver timeout (error %lu). Disabling it\n", GetLastError());
+               *Timeout = INFINITE;
+       }
+       else if (!SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, 0, &Enabled, 0))
+       {
+               WARN("WL: Unable to check if screen saver is enabled (error %lu). Disabling it\n", GetLastError());
+               *Timeout = INFINITE;
+       }
+       else if (!Enabled)
+       {
+               TRACE("WL: Screen saver is disabled\n");
+               *Timeout = INFINITE;
+       }
+       else
+       {
+               TRACE("WL: Screen saver timeout: %lu seconds\n", *Timeout);
+               *Timeout *= 1000;
+       }
+}
+
+static DWORD WINAPI
+ScreenSaverThreadMain(
+       IN LPVOID lpParameter)
+{
+       PWLSESSION Session = (PWLSESSION)lpParameter;
+       HANDLE HandleArray[3];
+#ifdef USE_GETLASTINPUTINFO
+       LASTINPUTINFO lastInputInfo;
+#else
+       DWORD LastActivity;
+#endif
+       DWORD TimeToWait;
+       DWORD Timeout; /* Timeout before screen saver starts, in milliseconds */
+       DWORD ret;
+
+       if (!ImpersonateLoggedOnUser(Session->UserToken))
+       {
+               ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
+               return 0;
+       }
+
+       Session->hUserActivity = CreateEventW(NULL, FALSE, FALSE, NULL);
+       if (!Session->hUserActivity)
+       {
+               ERR("WL: Unable to create event (error %lu)\n", GetLastError());
+               goto cleanup;
+       }
+
+       Session->hEndOfScreenSaver = CreateEventW(NULL, FALSE, FALSE, NULL);
+       if (!Session->hEndOfScreenSaver)
+       {
+               ERR("WL: Unable to create event (error %lu)\n", GetLastError());
+               goto cleanup;
+       }
+
+       HandleArray[0] = Session->hEndOfScreenSaverThread;
+       HandleArray[1] = Session->hScreenSaverParametersChanged;
+       HandleArray[2] = Session->hEndOfScreenSaver;
+
+       LoadScreenSaverParameters(&Timeout);
+
+#ifndef USE_GETLASTINPUTINFO
+       InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());
+#else
+       lastInputInfo.cbSize = sizeof(LASTINPUTINFO);
+#endif
+       for (;;)
+       {
+               /* See the time of last activity and calculate a timeout */
+#ifndef USE_GETLASTINPUTINFO
+               LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);
+               TimeToWait = Timeout - (GetTickCount() - LastActivity);
+#else
+               if (GetLastInputInfo(&lastInputInfo))
+                       TimeToWait = Timeout - (GetTickCount() - lastInputInfo.dwTime);
+               else
+               {
+                       WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());
+                       TimeToWait = 10; /* Try again in 10 ms */
+               }
+#endif
+               if (TimeToWait > Timeout)
+               {
+                       /* GetTickCount() got back to 0 */
+                       TimeToWait = Timeout;
+               }
+
+               /* Wait for the timeout, or the end of this thread */
+               ret = WaitForMultipleObjects(2, HandleArray, FALSE, TimeToWait);
+               if (ret == WAIT_OBJECT_0)
+                       break;
+               else if (ret == WAIT_OBJECT_0 + 1)
+                       LoadScreenSaverParameters(&Timeout);
+
+               /* Check if we didn't had recent activity */
+#ifndef USE_GETLASTINPUTINFO
+               LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);
+               if (LastActivity + Timeout > GetTickCount())
+                       continue;
+#else
+               if (!GetLastInputInfo(&lastInputInfo))
+               {
+                       WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());
+                       continue;
+               }
+               if (lastInputInfo.dwTime + Timeout > GetTickCount())
+                       continue;
+#endif
+
+               /* Run screen saver */
+               PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_TIMEOUT, 0);
+
+               /* Wait for the end of this thread or of the screen saver */
+               ret = WaitForMultipleObjects(3, HandleArray, FALSE, INFINITE);
+               if (ret == WAIT_OBJECT_0)
+                       break;
+               else if (ret == WAIT_OBJECT_0 + 1)
+                       LoadScreenSaverParameters(&Timeout);
+               else if (ret == WAIT_OBJECT_0 + 2)
+                       SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, FALSE, NULL, 0);
+       }
+
+cleanup:
+       RevertToSelf();
+       if (Session->hUserActivity)
+               CloseHandle(Session->hUserActivity);
+       if (Session->hEndOfScreenSaver)
+               CloseHandle(Session->hEndOfScreenSaver);
+#ifndef USE_GETLASTINPUTINFO
+       if (Session->KeyboardHook)
+               UnhookWindowsHookEx(Session->KeyboardHook);
+       if (Session->MouseHook)
+               UnhookWindowsHookEx(Session->MouseHook);
+#endif
+       CloseHandle(Session->hEndOfScreenSaverThread);
+       CloseHandle(Session->hScreenSaverParametersChanged);
+       return 0;
+}
+
+BOOL
+InitializeScreenSaver(
+       IN OUT PWLSESSION Session)
+{
+       HANDLE ScreenSaverThread;
+
+#ifndef USE_GETLASTINPUTINFO
+       /* Register hooks to detect keyboard and mouse activity */
+       Session->KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardActivityProc, hAppInstance, 0);
+       if (!Session->KeyboardHook)
+       {
+               ERR("WL: Unable to register keyboard hook\n");
+               return FALSE;
+       }
+       Session->MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseActivityProc, hAppInstance, 0);
+       if (!Session->MouseHook)
+       {
+               ERR("WL: Unable to register mouse hook\n");
+               return FALSE;
+       }
+#endif
+
+       Session->hScreenSaverParametersChanged = CreateEventW(NULL, FALSE, FALSE, NULL);
+       if (!Session->hScreenSaverParametersChanged)
+       {
+               WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());
+               return TRUE;
+       }
+       Session->hEndOfScreenSaverThread = CreateEventW(NULL, FALSE, FALSE, NULL);
+       if (!Session->hEndOfScreenSaverThread)
+       {
+               WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());
+               CloseHandle(Session->hScreenSaverParametersChanged);
+               return TRUE;
+       }
+
+       ScreenSaverThread = CreateThread(
+               NULL,
+               0,
+               ScreenSaverThreadMain,
+               Session,
+               0,
+               NULL);
+       if (ScreenSaverThread)
+               CloseHandle(ScreenSaverThread);
+       else
+               WARN("WL: Unable to start screen saver thread\n");
+
+       return TRUE;
+}
+
+VOID
+StartScreenSaver(
+       IN PWLSESSION Session)
+{
+       HKEY hKey = NULL;
+       WCHAR szApplicationName[MAX_PATH];
+       WCHAR szCommandLine[MAX_PATH + 3];
+       DWORD bufferSize = sizeof(szApplicationName)- 1;
+       DWORD dwType;
+       STARTUPINFOW StartupInfo;
+       PROCESS_INFORMATION ProcessInformation;
+       HANDLE HandleArray[2];
+       LONG rc;
+       DWORD Status;
+       BOOL ret = FALSE;
+
+       if (!ImpersonateLoggedOnUser(Session->UserToken))
+       {
+               ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
+               goto cleanup;
+       }
+
+       rc = RegOpenKeyExW(
+               HKEY_CURRENT_USER,
+               L"Control Panel\\Desktop",
+               0,
+               KEY_QUERY_VALUE,
+               &hKey);
+       if (rc != ERROR_SUCCESS)
+               goto cleanup;
+
+       szApplicationName[bufferSize] = 0; /* Terminate the string */
+       rc = RegQueryValueExW(
+               hKey,
+               L"SCRNSAVE.EXE",
+               0,
+               &dwType,
+               (LPBYTE)szApplicationName,
+               &bufferSize);
+       if (rc != ERROR_SUCCESS || dwType != REG_SZ)
+               goto cleanup;
+
+       wsprintfW(szCommandLine, L"%s /s", szApplicationName);
+       TRACE("WL: Executing %S\n", szCommandLine);
+
+       ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));
+       ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
+       StartupInfo.cb = sizeof(STARTUPINFOW);
+       /* FIXME: run the screen saver on the screen saver desktop */
+       ret = CreateProcessW(
+               szApplicationName,
+               szCommandLine,
+               NULL,
+               NULL,
+               FALSE,
+               0,
+               NULL,
+               NULL,
+               &StartupInfo,
+               &ProcessInformation);
+       if (!ret)
+       {
+               WARN("WL: Unable to start %S, error %lu\n", szApplicationName, GetLastError());
+               goto cleanup;
+       }
+       CloseHandle(ProcessInformation.hThread);
+
+       SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0);
+
+       /* Wait the end of the process or some other activity */
+       ResetEvent(Session->hUserActivity);
+       HandleArray[0] = ProcessInformation.hProcess;
+       HandleArray[1] = Session->hUserActivity;
+       Status = WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE);
+       if (Status == WAIT_OBJECT_0 + 1)
+       {
+               /* Kill the screen saver */
+               TerminateProcess(ProcessInformation.hProcess, 0);
+       }
+       SetEvent(Session->hEndOfScreenSaver);
+
+       CloseHandle(ProcessInformation.hProcess);
+
+cleanup:
+       RevertToSelf();
+       if (hKey)
+               RegCloseKey(hKey);
+       if (!ret)
+       {
+               PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_ACTIVITY, 0);
+#ifndef USE_GETLASTINPUTINFO
+               InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());
+#endif
+       }
+}