Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenscreensaver.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Winlogon 00004 * FILE: base/system/winlogon/screensaver.c 00005 * PURPOSE: Screen saver management 00006 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include "winlogon.h" 00012 00013 #include <wine/debug.h> 00014 00015 WINE_DEFAULT_DEBUG_CHANNEL(winlogon); 00016 00017 /* FUNCTIONS ****************************************************************/ 00018 00019 #ifndef USE_GETLASTINPUTINFO 00020 static LRESULT CALLBACK 00021 KeyboardActivityProc( 00022 IN INT nCode, 00023 IN WPARAM wParam, 00024 IN LPARAM lParam) 00025 { 00026 InterlockedExchange((LONG*)&WLSession->LastActivity, ((PKBDLLHOOKSTRUCT)lParam)->time); 00027 return CallNextHookEx(NULL, nCode, wParam, lParam); 00028 } 00029 00030 static LRESULT CALLBACK 00031 MouseActivityProc( 00032 IN INT nCode, 00033 IN WPARAM wParam, 00034 IN LPARAM lParam) 00035 { 00036 InterlockedExchange((LONG*)&WLSession->LastActivity, ((PMSLLHOOKSTRUCT)lParam)->time); 00037 return CallNextHookEx(NULL, nCode, wParam, lParam); 00038 } 00039 #endif 00040 00041 static VOID 00042 LoadScreenSaverParameters( 00043 OUT LPDWORD Timeout) 00044 { 00045 BOOL Enabled; 00046 00047 if (!SystemParametersInfoW(SPI_GETSCREENSAVETIMEOUT, 0, Timeout, 0)) 00048 { 00049 WARN("WL: Unable to get screen saver timeout (error %lu). Disabling it\n", GetLastError()); 00050 *Timeout = INFINITE; 00051 } 00052 else if (!SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, 0, &Enabled, 0)) 00053 { 00054 WARN("WL: Unable to check if screen saver is enabled (error %lu). Disabling it\n", GetLastError()); 00055 *Timeout = INFINITE; 00056 } 00057 else if (!Enabled) 00058 { 00059 TRACE("WL: Screen saver is disabled\n"); 00060 *Timeout = INFINITE; 00061 } 00062 else 00063 { 00064 TRACE("WL: Screen saver timeout: %lu seconds\n", *Timeout); 00065 *Timeout *= 1000; 00066 } 00067 } 00068 00069 static DWORD WINAPI 00070 ScreenSaverThreadMain( 00071 IN LPVOID lpParameter) 00072 { 00073 PWLSESSION Session = (PWLSESSION)lpParameter; 00074 HANDLE HandleArray[3]; 00075 #ifdef USE_GETLASTINPUTINFO 00076 LASTINPUTINFO lastInputInfo; 00077 #else 00078 DWORD LastActivity; 00079 #endif 00080 DWORD TimeToWait; 00081 DWORD Timeout; /* Timeout before screen saver starts, in milliseconds */ 00082 DWORD ret; 00083 00084 if (!ImpersonateLoggedOnUser(Session->UserToken)) 00085 { 00086 ERR("ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 00087 return 0; 00088 } 00089 00090 Session->hUserActivity = CreateEventW(NULL, FALSE, FALSE, NULL); 00091 if (!Session->hUserActivity) 00092 { 00093 ERR("WL: Unable to create event (error %lu)\n", GetLastError()); 00094 goto cleanup; 00095 } 00096 00097 Session->hEndOfScreenSaver = CreateEventW(NULL, FALSE, FALSE, NULL); 00098 if (!Session->hEndOfScreenSaver) 00099 { 00100 ERR("WL: Unable to create event (error %lu)\n", GetLastError()); 00101 goto cleanup; 00102 } 00103 00104 HandleArray[0] = Session->hEndOfScreenSaverThread; 00105 HandleArray[1] = Session->hScreenSaverParametersChanged; 00106 HandleArray[2] = Session->hEndOfScreenSaver; 00107 00108 LoadScreenSaverParameters(&Timeout); 00109 00110 #ifndef USE_GETLASTINPUTINFO 00111 InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount()); 00112 #else 00113 lastInputInfo.cbSize = sizeof(LASTINPUTINFO); 00114 #endif 00115 for (;;) 00116 { 00117 /* See the time of last activity and calculate a timeout */ 00118 #ifndef USE_GETLASTINPUTINFO 00119 LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0); 00120 TimeToWait = Timeout - (GetTickCount() - LastActivity); 00121 #else 00122 if (GetLastInputInfo(&lastInputInfo)) 00123 TimeToWait = Timeout - (GetTickCount() - lastInputInfo.dwTime); 00124 else 00125 { 00126 WARN("GetLastInputInfo() failed with error %lu\n", GetLastError()); 00127 TimeToWait = 10; /* Try again in 10 ms */ 00128 } 00129 #endif 00130 if (TimeToWait > Timeout) 00131 { 00132 /* GetTickCount() got back to 0 */ 00133 TimeToWait = Timeout; 00134 } 00135 00136 /* Wait for the timeout, or the end of this thread */ 00137 ret = WaitForMultipleObjects(2, HandleArray, FALSE, TimeToWait); 00138 if (ret == WAIT_OBJECT_0) 00139 break; 00140 else if (ret == WAIT_OBJECT_0 + 1) 00141 LoadScreenSaverParameters(&Timeout); 00142 00143 /* Check if we didn't had recent activity */ 00144 #ifndef USE_GETLASTINPUTINFO 00145 LastActivity = InterlockedCompareExchange((LONG*)&Session->LastActivity, 0, 0); 00146 if (LastActivity + Timeout > GetTickCount()) 00147 continue; 00148 #else 00149 if (!GetLastInputInfo(&lastInputInfo)) 00150 { 00151 WARN("GetLastInputInfo() failed with error %lu\n", GetLastError()); 00152 continue; 00153 } 00154 if (lastInputInfo.dwTime + Timeout > GetTickCount()) 00155 continue; 00156 #endif 00157 00158 /* Run screen saver */ 00159 PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_TIMEOUT, 0); 00160 00161 /* Wait for the end of this thread or of the screen saver */ 00162 ret = WaitForMultipleObjects(3, HandleArray, FALSE, INFINITE); 00163 if (ret == WAIT_OBJECT_0) 00164 break; 00165 else if (ret == WAIT_OBJECT_0 + 1) 00166 LoadScreenSaverParameters(&Timeout); 00167 else if (ret == WAIT_OBJECT_0 + 2) 00168 SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, FALSE, NULL, 0); 00169 } 00170 00171 cleanup: 00172 RevertToSelf(); 00173 if (Session->hUserActivity) 00174 CloseHandle(Session->hUserActivity); 00175 if (Session->hEndOfScreenSaver) 00176 CloseHandle(Session->hEndOfScreenSaver); 00177 #ifndef USE_GETLASTINPUTINFO 00178 if (Session->KeyboardHook) 00179 UnhookWindowsHookEx(Session->KeyboardHook); 00180 if (Session->MouseHook) 00181 UnhookWindowsHookEx(Session->MouseHook); 00182 #endif 00183 CloseHandle(Session->hEndOfScreenSaverThread); 00184 CloseHandle(Session->hScreenSaverParametersChanged); 00185 return 0; 00186 } 00187 00188 BOOL 00189 InitializeScreenSaver( 00190 IN OUT PWLSESSION Session) 00191 { 00192 HANDLE ScreenSaverThread; 00193 00194 #ifndef USE_GETLASTINPUTINFO 00195 /* Register hooks to detect keyboard and mouse activity */ 00196 Session->KeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardActivityProc, hAppInstance, 0); 00197 if (!Session->KeyboardHook) 00198 { 00199 ERR("WL: Unable to register keyboard hook\n"); 00200 return FALSE; 00201 } 00202 Session->MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseActivityProc, hAppInstance, 0); 00203 if (!Session->MouseHook) 00204 { 00205 ERR("WL: Unable to register mouse hook\n"); 00206 return FALSE; 00207 } 00208 #endif 00209 00210 Session->hScreenSaverParametersChanged = CreateEventW(NULL, FALSE, FALSE, NULL); 00211 if (!Session->hScreenSaverParametersChanged) 00212 { 00213 WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError()); 00214 return TRUE; 00215 } 00216 Session->hEndOfScreenSaverThread = CreateEventW(NULL, FALSE, FALSE, NULL); 00217 if (!Session->hEndOfScreenSaverThread) 00218 { 00219 WARN("WL: Unable to create screen saver event (error %lu)\n", GetLastError()); 00220 CloseHandle(Session->hScreenSaverParametersChanged); 00221 return TRUE; 00222 } 00223 00224 ScreenSaverThread = CreateThread( 00225 NULL, 00226 0, 00227 ScreenSaverThreadMain, 00228 Session, 00229 0, 00230 NULL); 00231 if (ScreenSaverThread) 00232 CloseHandle(ScreenSaverThread); 00233 else 00234 ERR("WL: Unable to start screen saver thread\n"); 00235 00236 return TRUE; 00237 } 00238 00239 VOID 00240 StartScreenSaver( 00241 IN PWLSESSION Session) 00242 { 00243 HKEY hKey = NULL, hCurrentUser = NULL; 00244 WCHAR szApplicationName[MAX_PATH]; 00245 WCHAR szCommandLine[MAX_PATH + 3]; 00246 DWORD bufferSize = sizeof(szApplicationName) - sizeof(WCHAR); 00247 DWORD dwType; 00248 STARTUPINFOW StartupInfo; 00249 PROCESS_INFORMATION ProcessInformation; 00250 HANDLE HandleArray[2]; 00251 LONG rc; 00252 DWORD Status; 00253 BOOL ret = FALSE; 00254 00255 if (!ImpersonateLoggedOnUser(Session->UserToken)) 00256 { 00257 ERR("WL: ImpersonateLoggedOnUser() failed with error %lu\n", GetLastError()); 00258 goto cleanup; 00259 } 00260 00261 rc = RegOpenCurrentUser( 00262 KEY_READ, 00263 &hCurrentUser); 00264 if (rc != ERROR_SUCCESS) 00265 { 00266 ERR("WL: RegOpenCurrentUser Error!\n"); 00267 goto cleanup; 00268 } 00269 00270 rc = RegOpenKeyExW( 00271 hCurrentUser, 00272 L"Control Panel\\Desktop", 00273 0, 00274 KEY_QUERY_VALUE, 00275 &hKey); 00276 if (rc != ERROR_SUCCESS) 00277 { 00278 ERR("WL: RegOpenKeyEx Error!\n"); 00279 goto cleanup; 00280 } 00281 00282 rc = RegQueryValueExW( 00283 hKey, 00284 L"SCRNSAVE.EXE", 00285 0, 00286 &dwType, 00287 (LPBYTE)szApplicationName, 00288 &bufferSize); 00289 if (rc != ERROR_SUCCESS || dwType != REG_SZ) 00290 { 00291 ERR("WL: RegQueryValueEx Error!\n"); 00292 goto cleanup; 00293 } 00294 00295 if (bufferSize == 0) 00296 { 00297 ERR("WL: Buffer size is NULL!\n"); 00298 goto cleanup; 00299 } 00300 00301 szApplicationName[bufferSize / sizeof(WCHAR)] = 0; /* Terminate the string */ 00302 00303 if (wcslen(szApplicationName) == 0) 00304 { 00305 ERR("WL: Application Name length is zero!\n"); 00306 goto cleanup; 00307 } 00308 00309 wsprintfW(szCommandLine, L"%s /s", szApplicationName); 00310 TRACE("WL: Executing %S\n", szCommandLine); 00311 00312 ZeroMemory(&StartupInfo, sizeof(STARTUPINFOW)); 00313 ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION)); 00314 StartupInfo.cb = sizeof(STARTUPINFOW); 00315 StartupInfo.dwFlags = STARTF_SCRNSAVER; 00316 /* FIXME: run the screen saver on the screen saver desktop */ 00317 ret = CreateProcessW( 00318 szApplicationName, 00319 szCommandLine, 00320 NULL, 00321 NULL, 00322 FALSE, 00323 0, 00324 NULL, 00325 NULL, 00326 &StartupInfo, 00327 &ProcessInformation); 00328 if (!ret) 00329 { 00330 ERR("WL: Unable to start %S, error %lu\n", szApplicationName, GetLastError()); 00331 goto cleanup; 00332 } 00333 CloseHandle(ProcessInformation.hThread); 00334 00335 SystemParametersInfoW(SPI_SETSCREENSAVERRUNNING, TRUE, NULL, 0); 00336 00337 /* Wait the end of the process or some other activity */ 00338 ResetEvent(Session->hUserActivity); 00339 HandleArray[0] = ProcessInformation.hProcess; 00340 HandleArray[1] = Session->hUserActivity; 00341 Status = WaitForMultipleObjects(2, HandleArray, FALSE, INFINITE); 00342 if (Status == WAIT_OBJECT_0 + 1) 00343 { 00344 /* Kill the screen saver */ 00345 TerminateProcess(ProcessInformation.hProcess, 0); 00346 } 00347 SetEvent(Session->hEndOfScreenSaver); 00348 00349 CloseHandle(ProcessInformation.hProcess); 00350 00351 cleanup: 00352 RevertToSelf(); 00353 if (hKey) 00354 RegCloseKey(hKey); 00355 if (hCurrentUser) 00356 RegCloseKey(hCurrentUser); 00357 if (!ret) 00358 { 00359 PostMessageW(Session->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_SCRNSVR_ACTIVITY, 0); 00360 #ifndef USE_GETLASTINPUTINFO 00361 InterlockedExchange((LONG*)&Session->LastActivity, GetTickCount()); 00362 #endif 00363 } 00364 } Generated on Sat May 26 2012 04:17:45 for ReactOS by
1.7.6.1
|