ReactOS 0.4.16-dev-1204-gb627a42
screensaver.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winlogon
4 * FILE: base/system/winlogon/screensaver.c
5 * PURPOSE: Screen saver management
6 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.org)
7 */
8
9/* INCLUDES *****************************************************************/
10
11#include "winlogon.h"
12#include <winbase_undoc.h>
13
14/* FUNCTIONS ****************************************************************/
15
16#ifndef USE_GETLASTINPUTINFO
17static
20KeyboardActivityProc(
21 IN INT nCode,
24{
25 InterlockedExchange((LONG*)&WLSession->LastActivity, ((PKBDLLHOOKSTRUCT)lParam)->time);
26 return CallNextHookEx(NULL, nCode, wParam, lParam);
27}
28
29
30static
33MouseActivityProc(
34 IN INT nCode,
37{
38 InterlockedExchange((LONG*)&WLSession->LastActivity, ((PMSLLHOOKSTRUCT)lParam)->time);
39 return CallNextHookEx(NULL, nCode, wParam, lParam);
40}
41#endif
42
43
44static
45VOID
48{
50
52 {
53 WARN("WL: Unable to get screen saver timeout (error %lu). Disabling it\n", GetLastError());
55 }
57 {
58 WARN("WL: Unable to check if screen saver is enabled (error %lu). Disabling it\n", GetLastError());
60 }
61 else if (!Enabled)
62 {
63 TRACE("WL: Screen saver is disabled\n");
65 }
66 else
67 {
68 TRACE("WL: Screen saver timeout: %lu seconds\n", *Timeout);
69 *Timeout *= 1000;
70 }
71}
72
73
74static
78 IN LPVOID lpParameter)
79{
80 PWLSESSION Session = (PWLSESSION)lpParameter;
81 HANDLE HandleArray[3];
82#ifdef USE_GETLASTINPUTINFO
83 LASTINPUTINFO lastInputInfo;
84#else
85 DWORD LastActivity;
86#endif
87 DWORD TimeToWait;
88 DWORD Timeout; /* Timeout before screen saver starts, in milliseconds */
89 DWORD ret;
90
92 {
93 ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
94 return 0;
95 }
96
98 if (!Session->hUserActivity)
99 {
100 ERR("WL: Unable to create event (error %lu)\n", GetLastError());
101 goto cleanup;
102 }
103
105 if (!Session->hEndOfScreenSaver)
106 {
107 ERR("WL: Unable to create event (error %lu)\n", GetLastError());
108 goto cleanup;
109 }
110
111 HandleArray[0] = Session->hEndOfScreenSaverThread;
112 HandleArray[1] = Session->hScreenSaverParametersChanged;
113 HandleArray[2] = Session->hEndOfScreenSaver;
114
116
117#ifndef USE_GETLASTINPUTINFO
118 InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());
119#else
120 lastInputInfo.cbSize = sizeof(LASTINPUTINFO);
121#endif
122 for (;;)
123 {
124 /* See the time of last activity and calculate a timeout */
125#ifndef USE_GETLASTINPUTINFO
126 LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);
127 TimeToWait = Timeout - (GetTickCount() - LastActivity);
128#else
129 if (GetLastInputInfo(&lastInputInfo))
130 TimeToWait = Timeout - (GetTickCount() - lastInputInfo.dwTime);
131 else
132 {
133 WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());
134 TimeToWait = 10; /* Try again in 10 ms */
135 }
136#endif
137
138 if (TimeToWait > Timeout)
139 {
140 /* GetTickCount() got back to 0 */
141 TimeToWait = Timeout;
142 }
143
144 /* Wait for the timeout, or the end of this thread */
145 ret = WaitForMultipleObjects(2, HandleArray, FALSE, TimeToWait);
146 if (ret == WAIT_OBJECT_0)
147 break;
148 else if (ret == WAIT_OBJECT_0 + 1)
150
151 /* Check if we didn't had recent activity */
152#ifndef USE_GETLASTINPUTINFO
153 LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0);
154 if (LastActivity + Timeout > GetTickCount())
155 continue;
156#else
157 if (!GetLastInputInfo(&lastInputInfo))
158 {
159 WARN("GetLastInputInfo() failed with error %lu\n", GetLastError());
160 continue;
161 }
162
163 if (lastInputInfo.dwTime + Timeout > GetTickCount())
164 continue;
165#endif
166
167 /* Run screen saver */
169
170 /* Wait for the end of this thread or of the screen saver */
171 ret = WaitForMultipleObjects(3, HandleArray, FALSE, INFINITE);
172 if (ret == WAIT_OBJECT_0)
173 break;
174 else if (ret == WAIT_OBJECT_0 + 1)
176 else if (ret == WAIT_OBJECT_0 + 2)
177 SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, FALSE, NULL, 0);
178 }
179
180cleanup:
181 if (Session->hUserActivity)
182 CloseHandle(Session->hUserActivity);
183
184 if (Session->hEndOfScreenSaver)
186
187 RevertToSelf();
188
189#ifndef USE_GETLASTINPUTINFO
190 if (Session->KeyboardHook)
191 UnhookWindowsHookEx(Session->KeyboardHook);
192
193 if (Session->MouseHook)
194 UnhookWindowsHookEx(Session->MouseHook);
195#endif
196
199
200 return 0;
201}
202
203
204BOOL
206 IN OUT PWLSESSION Session)
207{
208 HANDLE ScreenSaverThread;
209
210#ifndef USE_GETLASTINPUTINFO
211 /* Register hooks to detect keyboard and mouse activity */
212 Session->KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardActivityProc, hAppInstance, 0);
213 if (!Session->KeyboardHook)
214 {
215 ERR("WL: Unable to register keyboard hook\n");
216 return FALSE;
217 }
218
219 Session->MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseActivityProc, hAppInstance, 0);
220 if (!Session->MouseHook)
221 {
222 ERR("WL: Unable to register mouse hook\n");
223 return FALSE;
224 }
225#endif
226
227 Session->hScreenSaverParametersChanged = CreateEventW(NULL, FALSE, FALSE, NULL);
228 if (!Session->hScreenSaverParametersChanged)
229 {
230 WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());
231 return TRUE;
232 }
233
234 Session->hEndOfScreenSaverThread = CreateEventW(NULL, FALSE, FALSE, NULL);
235 if (!Session->hEndOfScreenSaverThread)
236 {
237 WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError());
238 CloseHandle(Session->hScreenSaverParametersChanged);
239 return TRUE;
240 }
241
242 ScreenSaverThread = CreateThread(NULL,
243 0,
245 Session,
246 0,
247 NULL);
248 if (ScreenSaverThread)
249 CloseHandle(ScreenSaverThread);
250 else
251 ERR("WL: Unable to start screen saver thread\n");
252
253 return TRUE;
254}
255
256
257VOID
259 IN PWLSESSION Session)
260{
261 HKEY hKey = NULL, hCurrentUser = NULL;
262 WCHAR szApplicationName[MAX_PATH];
263 WCHAR szCommandLine[MAX_PATH + 3];
264 DWORD bufferSize = sizeof(szApplicationName) - sizeof(WCHAR);
265 DWORD dwType;
266 STARTUPINFOW StartupInfo;
267 PROCESS_INFORMATION ProcessInformation;
268 HANDLE HandleArray[2];
269 LONG rc;
271 BOOL ret = FALSE;
272
273 if (!ImpersonateLoggedOnUser(Session->UserToken))
274 {
275 ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError());
276 goto cleanup;
277 }
278
280 &hCurrentUser);
281 if (rc != ERROR_SUCCESS)
282 {
283 ERR("WL: RegOpenCurrentUser error %lu\n", rc);
284 goto cleanup;
285 }
286
287 rc = RegOpenKeyExW(hCurrentUser,
288 L"Control Panel\\Desktop",
289 0,
291 &hKey);
292 if (rc != ERROR_SUCCESS)
293 {
294 ERR("WL: RegOpenKeyEx error %lu\n", rc);
295 goto cleanup;
296 }
297
299 L"SCRNSAVE.EXE",
300 0,
301 &dwType,
302 (LPBYTE)szApplicationName,
303 &bufferSize);
304 if (rc != ERROR_SUCCESS || dwType != REG_SZ)
305 {
306 if (rc != ERROR_FILE_NOT_FOUND)
307 ERR("WL: RegQueryValueEx error %lu\n", rc);
308 goto cleanup;
309 }
310
311 if (bufferSize == 0)
312 {
313 ERR("WL: Buffer size is NULL!\n");
314 goto cleanup;
315 }
316
317 szApplicationName[bufferSize / sizeof(WCHAR)] = 0; /* Terminate the string */
318
319 if (wcslen(szApplicationName) == 0)
320 {
321 ERR("WL: Application Name length is zero!\n");
322 goto cleanup;
323 }
324
325 wsprintfW(szCommandLine, L"%s /s", szApplicationName);
326 TRACE("WL: Executing %S\n", szCommandLine);
327
328 ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW));
329 ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
330 StartupInfo.cb = sizeof(STARTUPINFOW);
331 StartupInfo.dwFlags = STARTF_SCREENSAVER;
332
333 /* FIXME: Run the screen saver on the secure screen saver desktop if required */
334 StartupInfo.lpDesktop = L"WinSta0\\Default";
335
336 ret = CreateProcessAsUserW(Session->UserToken,
337 szApplicationName,
338 szCommandLine,
339 NULL,
340 NULL,
341 FALSE,
343 NULL,
344 NULL,
345 &StartupInfo,
346 &ProcessInformation);
347 if (!ret)
348 {
349 ERR("WL: Unable to start %S, error %lu\n", szApplicationName, GetLastError());
350 goto cleanup;
351 }
352
353 CloseHandle(ProcessInformation.hThread);
354
355 SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0);
356
358
359 /* Wait the end of the process or some other activity */
360 ResetEvent(Session->hUserActivity);
361 HandleArray[0] = ProcessInformation.hProcess;
362 HandleArray[1] = Session->hUserActivity;
363 Status = WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE);
364 if (Status == WAIT_OBJECT_0 + 1)
365 {
366 /* Kill the screen saver */
367 TerminateProcess(ProcessInformation.hProcess, 0);
368 }
369
370 SetEvent(Session->hEndOfScreenSaver);
371
372 CloseHandle(ProcessInformation.hProcess);
373
375
376cleanup:
377 if (hKey)
379
380 if (hCurrentUser)
381 RegCloseKey(hCurrentUser);
382
383 RevertToSelf();
384
385 if (!ret)
386 {
388#ifndef USE_GETLASTINPUTINFO
389 InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount());
390#endif
391 }
392}
#define InterlockedExchange
Definition: armddk.h:54
HINSTANCE hAppInstance
Definition: mmc.c:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
VOID CallNotificationDlls(PWLSESSION pSession, NOTIFICATION_TYPE Type)
Definition: notify.c:390
static DWORD WINAPI ScreenSaverThreadMain(IN LPVOID lpParameter)
Definition: screensaver.c:77
static VOID LoadScreenSaverParameters(OUT LPDWORD Timeout)
Definition: screensaver.c:46
BOOL InitializeScreenSaver(IN OUT PWLSESSION Session)
Definition: screensaver.c:205
VOID StartScreenSaver(IN PWLSESSION Session)
Definition: screensaver.c:258
#define RegCloseKey(hKey)
Definition: registry.h:49
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessAsUserW(_In_opt_ HANDLE hToken, _In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation)
Definition: logon.c:993
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegOpenCurrentUser(IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3209
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
BOOL WINAPI ImpersonateLoggedOnUser(HANDLE hToken)
Definition: misc.c:152
#define CloseHandle
Definition: compat.h:739
#define MAX_PATH
Definition: compat.h:34
#define CALLBACK
Definition: compat.h:35
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
size_t bufferSize
Status
Definition: gdiplustypes.h:25
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define REG_SZ
Definition: layer.c:22
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
@ Enabled
Definition: mountmgr.h:179
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
static ULONG Timeout
Definition: ping.c:61
#define TRACE(s)
Definition: solgame.cpp:4
LPWSTR lpDesktop
Definition: winbase.h:889
DWORD cb
Definition: winbase.h:887
DWORD dwFlags
Definition: winbase.h:898
HANDLE hUserActivity
Definition: winlogon.h:246
HANDLE hScreenSaverParametersChanged
Definition: winlogon.h:245
HANDLE hEndOfScreenSaver
Definition: winlogon.h:247
HANDLE UserToken
Definition: winlogon.h:233
HANDLE hEndOfScreenSaverThread
Definition: winlogon.h:244
HWND SASWindow
Definition: winlogon.h:226
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define STARTF_SCREENSAVER
Definition: undocuser.h:168
int ret
#define ZeroMemory
Definition: winbase.h:1753
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:439
#define IDLE_PRIORITY_CLASS
Definition: winbase.h:192
BOOL WINAPI RevertToSelf(void)
Definition: security.c:1608
struct _STARTUPINFOW STARTUPINFOW
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define WINAPI
Definition: msvc.h:6
PWLSESSION WLSession
Definition: winlogon.c:20
struct _WLSESSION * PWLSESSION
@ StopScreenSaverHandler
Definition: winlogon.h:267
@ StartScreenSaverHandler
Definition: winlogon.h:266
BOOL WINAPI GetLastInputInfo(_Out_ PLASTINPUTINFO)
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define SetWindowsHookEx
Definition: winuser.h:5941
#define WH_MOUSE_LL
Definition: winuser.h:44
BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK)
#define WH_KEYBOARD_LL
Definition: winuser.h:43
BOOL WINAPI SystemParametersInfoW(_In_ UINT uiAction, _In_ UINT uiParam, _Inout_opt_ PVOID pvParam, _In_ UINT fWinIni)
LRESULT WINAPI CallNextHookEx(_In_opt_ HHOOK, _In_ int, _In_ WPARAM, _In_ LPARAM)
#define SPI_GETSCREENSAVETIMEOUT
Definition: winuser.h:1374
#define SPI_GETSCREENSAVEACTIVE
Definition: winuser.h:1376
struct tagLASTINPUTINFO LASTINPUTINFO
#define WLX_WM_SAS
Definition: winwlx.h:71
#define WLX_SAS_TYPE_SCRNSVR_TIMEOUT
Definition: winwlx.h:37
#define WLX_SAS_TYPE_SCRNSVR_ACTIVITY
Definition: winwlx.h:38
__wchar_t WCHAR
Definition: xmlstorage.h:180