ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

screensaver.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.