xref: /reactos/dll/cpl/desk/screensaver.c (revision 7244e0c5)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Display Control Panel
4  * FILE:            dll/cpl/desk/screensaver.c
5  * PURPOSE:         Screen saver property page
6  *
7  * PROGRAMMERS:     Trevor McCort (lycan359@gmail.com)
8  *                  Ged Murphy (gedmurphy@reactos.org)
9  */
10 
11 #include "desk.h"
12 
13 #define MAX_SCREENSAVERS 100
14 
15 static const TCHAR szPreviewWndClass[] = TEXT("SSDemoParent");
16 
17 typedef struct
18 {
19     BOOL  bIsScreenSaver; /* Is this background a wallpaper */
20     TCHAR szFilename[MAX_PATH];
21     TCHAR szDisplayName[256];
22 } ScreenSaverItem;
23 
24 
25 typedef struct _DATA
26 {
27     ScreenSaverItem     ScreenSaverItems[MAX_SCREENSAVERS];
28     PROCESS_INFORMATION PrevWindowPi;
29     int                 Selection;
30     WNDPROC             OldPreviewProc;
31     UINT                ScreenSaverCount;
32     HWND                ScreenSaverPreviewParent;
33 } DATA, *PDATA;
34 
35 
36 static LPTSTR
37 GetCurrentScreenSaverValue(LPTSTR lpValue)
38 {
39     HKEY hKey;
40     LPTSTR lpBuf = NULL;
41     DWORD BufSize, Type = REG_SZ;
42     LONG Ret;
43 
44     Ret = RegOpenKeyEx(HKEY_CURRENT_USER,
45                        _T("Control Panel\\Desktop"),
46                        0,
47                        KEY_READ,
48                        &hKey);
49     if (Ret != ERROR_SUCCESS)
50         return NULL;
51 
52     Ret = RegQueryValueEx(hKey,
53                           lpValue,
54                           0,
55                           &Type,
56                           NULL,
57                           &BufSize);
58     if (Ret == ERROR_SUCCESS)
59     {
60         lpBuf = HeapAlloc(GetProcessHeap(),
61                           0,
62                           BufSize);
63         if (lpBuf)
64         {
65             Ret = RegQueryValueEx(hKey,
66                                   lpValue,
67                                   0,
68                                   &Type,
69                                   (LPBYTE)lpBuf,
70                                   &BufSize);
71             if (Ret != ERROR_SUCCESS)
72             {
73                 HeapFree(GetProcessHeap(), 0, lpBuf);
74                 lpBuf = NULL;
75             }
76         }
77     }
78 
79     RegCloseKey(hKey);
80 
81     return lpBuf;
82 }
83 
84 
85 static VOID
86 SelectionChanged(HWND hwndDlg, PDATA pData)
87 {
88     HWND hwndCombo;
89     BOOL bEnable;
90     INT i;
91 
92     hwndCombo = GetDlgItem(hwndDlg, IDC_SCREENS_LIST);
93 
94     i = (INT)SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
95     i = (INT)SendMessage(hwndCombo, CB_GETITEMDATA, i, 0);
96 
97     pData->Selection = i;
98 
99     bEnable = (i != 0);
100 
101     EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_SETTINGS), bEnable);
102     EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TESTSC), bEnable);
103     EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_USEPASSCHK), bEnable);
104     EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TIMEDELAY), bEnable);
105     EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TIME), bEnable);
106     EnableWindow(GetDlgItem(hwndDlg, IDC_WAITTEXT), bEnable);
107     EnableWindow(GetDlgItem(hwndDlg, IDC_MINTEXT), bEnable);
108 }
109 
110 
111 LRESULT CALLBACK
112 RedrawSubclassProc(HWND hwndDlg,
113                    UINT uMsg,
114                    WPARAM wParam,
115                    LPARAM lParam)
116 {
117     HWND hwnd;
118     PDATA pData;
119     LRESULT Ret = FALSE;
120 
121     pData = (PDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
122     if (!pData)
123         return Ret;
124 
125     Ret = CallWindowProc(pData->OldPreviewProc, hwndDlg, uMsg, wParam, lParam);
126 
127     if (uMsg == WM_PAINT)
128     {
129         hwnd = pData->ScreenSaverPreviewParent;
130         if (hwnd)
131             RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
132     }
133 
134     return Ret;
135 }
136 
137 
138 static VOID
139 ShowScreenSaverPreview(IN LPDRAWITEMSTRUCT draw, IN PDATA pData)
140 {
141     HBRUSH hBrush;
142     HDC hDC;
143     HGDIOBJ hOldObj;
144     RECT rcItem = {
145         MONITOR_LEFT,
146         MONITOR_TOP,
147         MONITOR_RIGHT,
148         MONITOR_BOTTOM
149     };
150 
151     hDC = CreateCompatibleDC(draw->hDC);
152     hOldObj = SelectObject(hDC, g_GlobalData.hMonitorBitmap);
153 
154     if (!IsWindowVisible(pData->ScreenSaverPreviewParent))
155     {
156         /* FIXME: Draw static bitmap inside monitor. */
157         hBrush = CreateSolidBrush(g_GlobalData.desktop_color);
158         FillRect(hDC, &rcItem, hBrush);
159         DeleteObject(hBrush);
160     }
161 
162     GdiTransparentBlt(draw->hDC,
163                       draw->rcItem.left, draw->rcItem.top,
164                       draw->rcItem.right - draw->rcItem.left + 1,
165                       draw->rcItem.bottom - draw->rcItem.top + 1,
166                       hDC,
167                       0, 0,
168                       g_GlobalData.bmMonWidth, g_GlobalData.bmMonHeight,
169                       MONITOR_ALPHA);
170 
171     SelectObject(hDC, hOldObj);
172     DeleteDC(hDC);
173 }
174 
175 
176 static VOID
177 SetScreenSaverPreviewBox(HWND hwndDlg, PDATA pData)
178 {
179     HWND hPreview = pData->ScreenSaverPreviewParent;
180     STARTUPINFO si;
181     TCHAR szCmdline[2048];
182 
183     /* Kill off the previous preview process */
184     if (pData->PrevWindowPi.hProcess)
185     {
186         TerminateProcess(pData->PrevWindowPi.hProcess, 0);
187         CloseHandle(pData->PrevWindowPi.hProcess);
188         CloseHandle(pData->PrevWindowPi.hThread);
189         pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL;
190     }
191     ShowWindow(pData->ScreenSaverPreviewParent, SW_HIDE);
192 
193     if (pData->Selection > 0)
194     {
195         _stprintf(szCmdline,
196                   _T("%s /p %Iu"),
197                   pData->ScreenSaverItems[pData->Selection].szFilename,
198                   (ULONG_PTR)hPreview);
199 
200         ZeroMemory(&si, sizeof(si));
201         si.cb = sizeof(si);
202         ZeroMemory(&pData->PrevWindowPi, sizeof(pData->PrevWindowPi));
203 
204         ShowWindow(pData->ScreenSaverPreviewParent, SW_SHOW);
205 
206         if (!CreateProcess(NULL,
207                            szCmdline,
208                            NULL,
209                            NULL,
210                            FALSE,
211                            0,
212                            NULL,
213                            NULL,
214                            &si,
215                            &pData->PrevWindowPi))
216         {
217             pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL;
218         }
219     }
220 }
221 
222 static BOOL
223 WaitForSettingsDialog(HWND hwndDlg,
224                       HANDLE hProcess)
225 {
226     DWORD dwResult;
227     MSG msg;
228 
229     while (TRUE)
230     {
231         dwResult = MsgWaitForMultipleObjects(1,
232                                              &hProcess,
233                                              FALSE,
234                                              INFINITE,
235                                              QS_ALLINPUT);
236         if (dwResult == WAIT_OBJECT_0 + 1)
237         {
238             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
239             {
240                 if (msg.message == WM_QUIT)
241                 {
242                     return FALSE;
243                 }
244                 if (IsDialogMessage(hwndDlg, &msg))
245                 {
246                     TranslateMessage(&msg);
247                     DispatchMessage(&msg);
248                 }
249             }
250             else
251             {
252                 return FALSE;
253             }
254         }
255         else if (dwResult == WAIT_OBJECT_0)
256         {
257             return TRUE;
258         }
259         else
260         {
261             return FALSE;
262         }
263     }
264 }
265 
266 
267 static VOID
268 ScreensaverConfig(HWND hwndDlg, PDATA pData)
269 {
270     /*
271      * /c:<hwnd>  Run configuration, hwnd is handle of calling window
272      */
273 
274     TCHAR szCmdline[2048];
275     STARTUPINFO si;
276     PROCESS_INFORMATION pi;
277 
278     if (pData->Selection < 1)
279         return;
280 
281     _stprintf(szCmdline,
282               _T("%s /c:%Iu"),
283               pData->ScreenSaverItems[pData->Selection].szFilename,
284               (ULONG_PTR)hwndDlg);
285 
286     ZeroMemory(&si, sizeof(si));
287     si.cb = sizeof(si);
288     ZeroMemory(&pi, sizeof(pi));
289     if (CreateProcess(NULL,
290                      szCmdline,
291                      NULL,
292                      NULL,
293                      FALSE,
294                      0,
295                      NULL,
296                      NULL,
297                      &si,
298                      &pi))
299     {
300         /* Kill off the previous preview process */
301         if (pData->PrevWindowPi.hProcess)
302         {
303             TerminateProcess(pData->PrevWindowPi.hProcess, 0);
304             CloseHandle(pData->PrevWindowPi.hProcess);
305             CloseHandle(pData->PrevWindowPi.hThread);
306             pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL;
307         }
308 
309         if (WaitForSettingsDialog(hwndDlg, pi.hProcess))
310             SetScreenSaverPreviewBox(hwndDlg, pData);
311     }
312 }
313 
314 
315 static VOID
316 ScreensaverPreview(HWND hwndDlg, PDATA pData)
317 {
318     /*
319        /s         Run normal
320     */
321 
322     TCHAR szCmdline[2048];
323     STARTUPINFO si;
324     PROCESS_INFORMATION pi;
325 
326     if (pData->Selection < 1)
327         return;
328 
329     /* Kill off the previous preview process */
330     if (pData->PrevWindowPi.hProcess)
331     {
332         TerminateProcess(pData->PrevWindowPi.hProcess, 0);
333         CloseHandle(pData->PrevWindowPi.hProcess);
334         CloseHandle(pData->PrevWindowPi.hThread);
335         pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL;
336     }
337 
338     _stprintf(szCmdline,
339               _T("%s /s"),
340               pData->ScreenSaverItems[pData->Selection].szFilename);
341 
342     ZeroMemory(&si, sizeof(si));
343     si.cb = sizeof(si);
344     ZeroMemory(&pi, sizeof(pi));
345     if (CreateProcess(NULL,
346                      szCmdline,
347                      NULL,
348                      NULL,
349                      FALSE,
350                      0,
351                      NULL,
352                      NULL,
353                      &si,
354                      &pi))
355     {
356         WaitForSingleObject(pi.hProcess, INFINITE);
357         CloseHandle(pi.hProcess);
358         CloseHandle(pi.hThread);
359     }
360 }
361 
362 
363 static VOID
364 CheckRegScreenSaverIsSecure(HWND hwndDlg)
365 {
366     HKEY hKey;
367     TCHAR szBuffer[2];
368     DWORD bufferSize = sizeof(szBuffer);
369     DWORD varType = REG_SZ;
370     LONG result;
371 
372     if (RegOpenKeyEx(HKEY_CURRENT_USER,
373                      _T("Control Panel\\Desktop"),
374                      0,
375                      KEY_ALL_ACCESS,
376                      &hKey) == ERROR_SUCCESS)
377     {
378         result = RegQueryValueEx(hKey,
379                                 _T("ScreenSaverIsSecure"),
380                                 0,
381                                 &varType,
382                                 (LPBYTE)szBuffer,
383                                 &bufferSize);
384         RegCloseKey(hKey);
385 
386         if (result == ERROR_SUCCESS)
387         {
388             if (_ttoi(szBuffer) == 1)
389             {
390                 SendDlgItemMessage(hwndDlg,
391                                    IDC_SCREENS_USEPASSCHK,
392                                    BM_SETCHECK,
393                                    (WPARAM)BST_CHECKED,
394                                    0);
395                 return;
396             }
397         }
398 
399         SendDlgItemMessage(hwndDlg,
400                            IDC_SCREENS_USEPASSCHK,
401                            BM_SETCHECK,
402                            (WPARAM)BST_UNCHECKED,
403                            0);
404     }
405 }
406 
407 
408 static VOID
409 SearchScreenSavers(HWND hwndScreenSavers,
410                    LPCTSTR pszSearchPath,
411                    PDATA pData)
412 {
413     WIN32_FIND_DATA  fd;
414     TCHAR            szSearchPath[MAX_PATH];
415     HANDLE           hFind;
416     ScreenSaverItem *ScreenSaverItem;
417     HANDLE           hModule;
418     UINT             i, ScreenSaverCount;
419     HRESULT hr;
420 
421     ScreenSaverCount = pData->ScreenSaverCount;
422 
423     hr = StringCbCopy(szSearchPath, sizeof(szSearchPath), pszSearchPath);
424     if (FAILED(hr))
425         return;
426     hr = StringCbCat(szSearchPath, sizeof(szSearchPath), TEXT("\\*.scr"));
427     if (FAILED(hr))
428         return;
429 
430     hFind = FindFirstFile(szSearchPath, &fd);
431 
432     if (hFind == INVALID_HANDLE_VALUE)
433         return;
434 
435     while (ScreenSaverCount < MAX_SCREENSAVERS)
436     {
437         /* Don't add any hidden screensavers */
438         if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0)
439         {
440             TCHAR filename[MAX_PATH];
441 
442             hr = StringCbCopy(filename, sizeof(filename), pszSearchPath);
443             if (FAILED(hr))
444             {
445                 FindClose(hFind);
446                 return;
447             }
448             hr = StringCbCat(filename, sizeof(filename), _T("\\"));
449             if (FAILED(hr))
450             {
451                 FindClose(hFind);
452                 return;
453             }
454             hr = StringCbCat(filename, sizeof(filename), fd.cFileName);
455             if (FAILED(hr))
456             {
457                 FindClose(hFind);
458                 return;
459             }
460 
461             ScreenSaverItem = pData->ScreenSaverItems + ScreenSaverCount;
462 
463             ScreenSaverItem->bIsScreenSaver = TRUE;
464 
465             hModule = LoadLibraryEx(filename,
466                                     NULL,
467                                     DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
468             if (hModule)
469             {
470                 if (0 == LoadString(hModule,
471                           1,
472                           ScreenSaverItem->szDisplayName,
473                           sizeof(ScreenSaverItem->szDisplayName) / sizeof(TCHAR)))
474                 {
475                     // If the string does not exists, copy the name of the file
476                     hr = StringCbCopy(ScreenSaverItem->szDisplayName, sizeof(ScreenSaverItem->szDisplayName), fd.cFileName);
477                     if (FAILED(hr))
478                     {
479                         FreeLibrary(hModule);
480                         FindClose(hFind);
481                         return;
482                     }
483                     ScreenSaverItem->szDisplayName[_tcslen(fd.cFileName)-4] = '\0';
484                 }
485                 FreeLibrary(hModule);
486             }
487             else
488             {
489                 hr = StringCbCopy(ScreenSaverItem->szDisplayName, sizeof(ScreenSaverItem->szDisplayName), _T("Unknown"));
490                 if (FAILED(hr))
491                 {
492                     FindClose(hFind);
493                     return;
494                 }
495             }
496 
497             hr = StringCbCopy(ScreenSaverItem->szFilename, sizeof(ScreenSaverItem->szFilename), filename);
498             if (FAILED(hr))
499             {
500                 FindClose(hFind);
501                 return;
502             }
503 
504             i = SendMessage(hwndScreenSavers,
505                             CB_ADDSTRING,
506                             0,
507                             (LPARAM)ScreenSaverItem->szDisplayName);
508 
509             SendMessage(hwndScreenSavers,
510                         CB_SETITEMDATA,
511                         i,
512                         (LPARAM)ScreenSaverCount);
513 
514             ScreenSaverCount++;
515         }
516 
517         if (!FindNextFile(hFind, &fd))
518             break;
519     }
520 
521     FindClose(hFind);
522 
523     pData->ScreenSaverCount = ScreenSaverCount;
524 }
525 
526 
527 static VOID
528 AddScreenSavers(HWND hwndDlg, PDATA pData)
529 {
530     HWND hwndScreenSavers = GetDlgItem(hwndDlg, IDC_SCREENS_LIST);
531     TCHAR szSearchPath[MAX_PATH];
532     TCHAR szLocalPath[MAX_PATH];
533     INT i;
534     ScreenSaverItem *ScreenSaverItem = NULL;
535     LPTSTR lpBackSlash;
536 
537     /* Add the "None" item */
538     ScreenSaverItem = pData->ScreenSaverItems;
539 
540     ScreenSaverItem->bIsScreenSaver = FALSE;
541 
542     LoadString(hApplet,
543                IDS_NONE,
544                ScreenSaverItem->szDisplayName,
545                sizeof(ScreenSaverItem->szDisplayName) / sizeof(TCHAR));
546 
547     i = SendMessage(hwndScreenSavers,
548                     CB_ADDSTRING,
549                     0,
550                     (LPARAM)ScreenSaverItem->szDisplayName);
551 
552     SendMessage(hwndScreenSavers,
553                 CB_SETITEMDATA,
554                 i,
555                 (LPARAM)0);
556 
557     // Initialize number of items into the list
558     pData->ScreenSaverCount = 1;
559 
560     // Add all the screensavers where the applet is stored.
561     GetModuleFileName(hApplet, szLocalPath, MAX_PATH);
562     lpBackSlash = _tcsrchr(szLocalPath, _T('\\'));
563     if (lpBackSlash != NULL)
564     {
565         *lpBackSlash = '\0';
566         SearchScreenSavers(hwndScreenSavers, szLocalPath, pData);
567     }
568 
569     // Add all the screensavers in the C:\ReactOS\System32 directory.
570     GetSystemDirectory(szSearchPath, MAX_PATH);
571     if (lpBackSlash != NULL && _tcsicmp(szSearchPath, szLocalPath) != 0)
572         SearchScreenSavers(hwndScreenSavers, szSearchPath, pData);
573 
574     // Add all the screensavers in the C:\ReactOS directory.
575     GetWindowsDirectory(szSearchPath, MAX_PATH);
576     if (lpBackSlash != NULL && _tcsicmp(szSearchPath, szLocalPath) != 0)
577         SearchScreenSavers(hwndScreenSavers, szSearchPath, pData);
578 }
579 
580 
581 static VOID
582 SetScreenSaver(HWND hwndDlg, PDATA pData)
583 {
584     HKEY regKey;
585     BOOL DeleteMode = FALSE;
586 
587     DBG_UNREFERENCED_LOCAL_VARIABLE(DeleteMode);
588 
589     if (RegOpenKeyEx(HKEY_CURRENT_USER,
590                      _T("Control Panel\\Desktop"),
591                      0,
592                      KEY_ALL_ACCESS,
593                      &regKey) == ERROR_SUCCESS)
594     {
595         INT Time;
596         BOOL bRet;
597         TCHAR Sec;
598         UINT Ret;
599 
600         /* Set the screensaver */
601         if (pData->ScreenSaverItems[pData->Selection].bIsScreenSaver)
602         {
603             SIZE_T Length = _tcslen(pData->ScreenSaverItems[pData->Selection].szFilename) * sizeof(TCHAR);
604             RegSetValueEx(regKey,
605                           _T("SCRNSAVE.EXE"),
606                           0,
607                           REG_SZ,
608                           (PBYTE)pData->ScreenSaverItems[pData->Selection].szFilename,
609                           (DWORD)Length);
610 
611             SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_UPDATEINIFILE);
612         }
613         else
614         {
615             /* Windows deletes the value if no screensaver is set */
616             RegDeleteValue(regKey, _T("SCRNSAVE.EXE"));
617             DeleteMode = TRUE;
618 
619             SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, 0, SPIF_UPDATEINIFILE);
620         }
621 
622         /* Set the secure value */
623         Ret = SendDlgItemMessage(hwndDlg,
624                                  IDC_SCREENS_USEPASSCHK,
625                                  BM_GETCHECK,
626                                  0,
627                                  0);
628         Sec = (Ret == BST_CHECKED) ? _T('1') : _T('0');
629         RegSetValueEx(regKey,
630                       _T("ScreenSaverIsSecure"),
631                       0,
632                       REG_SZ,
633                       (PBYTE)&Sec,
634                       sizeof(TCHAR));
635 
636         /* Set the screensaver time delay */
637         Time = GetDlgItemInt(hwndDlg,
638                              IDC_SCREENS_TIMEDELAY,
639                              &bRet,
640                              FALSE);
641         if (Time == 0)
642             Time = 60;
643         else
644             Time *= 60;
645 
646         SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT, Time, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
647 
648         RegCloseKey(regKey);
649     }
650 }
651 
652 
653 static BOOL
654 OnInitDialog(HWND hwndDlg, PDATA pData)
655 {
656     LPTSTR lpCurSs;
657     HWND hwndSSCombo = GetDlgItem(hwndDlg, IDC_SCREENS_LIST);
658     INT Num;
659     WNDCLASS wc = {0};
660 
661     pData = HeapAlloc(GetProcessHeap(),
662                             HEAP_ZERO_MEMORY,
663                             sizeof(DATA));
664     if (!pData)
665     {
666         EndDialog(hwndDlg, -1);
667         return FALSE;
668     }
669 
670     wc.lpfnWndProc = DefWindowProc;
671     wc.hInstance = hApplet;
672     wc.hCursor = NULL;
673     wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
674     wc.lpszClassName = szPreviewWndClass;
675 
676     if (RegisterClass(&wc))
677     {
678         HWND hParent = GetDlgItem(hwndDlg, IDC_SCREENS_PREVIEW);
679         HWND hChild;
680 
681         if (hParent != NULL)
682         {
683             pData->OldPreviewProc = (WNDPROC)GetWindowLongPtr(hParent, GWLP_WNDPROC);
684             SetWindowLongPtr(hParent, GWLP_WNDPROC, (LONG_PTR)RedrawSubclassProc);
685             SetWindowLongPtr(hParent, GWLP_USERDATA, (LONG_PTR)pData);
686         }
687 
688         hChild = CreateWindowEx(0, szPreviewWndClass, NULL,
689                                 WS_CHILD | WS_CLIPCHILDREN,
690                                 0, 0, 0, 0, hParent,
691                                 NULL, hApplet, NULL);
692         if (hChild != NULL)
693         {
694             RECT rc;
695             GetClientRect(hParent, &rc);
696             rc.left += MONITOR_LEFT;
697             rc.top += MONITOR_TOP;
698             MoveWindow(hChild, rc.left, rc.top, MONITOR_WIDTH, MONITOR_HEIGHT, FALSE);
699         }
700 
701         pData->ScreenSaverPreviewParent = hChild;
702     }
703 
704     SetWindowLongPtr(hwndDlg,
705                      DWLP_USER,
706                      (LONG_PTR)pData);
707 
708     pData->Selection = -1;
709 
710     SendDlgItemMessage(hwndDlg,
711                        IDC_SCREENS_TIME,
712                        UDM_SETRANGE,
713                        0,
714                        MAKELONG
715                        ((short) 240, (short) 1));
716 
717     AddScreenSavers(hwndDlg,
718                     pData);
719 
720     CheckRegScreenSaverIsSecure(hwndDlg);
721 
722     /* Set the current screensaver in the combo box */
723     lpCurSs = GetCurrentScreenSaverValue(_T("SCRNSAVE.EXE"));
724     if (lpCurSs)
725     {
726         BOOL bFound = FALSE;
727         INT i;
728 
729         for (i = 0; i < MAX_SCREENSAVERS; i++)
730         {
731             if (!_tcscmp(lpCurSs, pData->ScreenSaverItems[i].szFilename))
732             {
733                 bFound = TRUE;
734                 break;
735             }
736         }
737 
738         if (bFound)
739         {
740             Num = SendMessage(hwndSSCombo,
741                               CB_FINDSTRINGEXACT,
742                               -1,
743                               (LPARAM)pData->ScreenSaverItems[i].szDisplayName);
744             if (Num != CB_ERR)
745                 SendMessage(hwndSSCombo,
746                             CB_SETCURSEL,
747                             Num,
748                             0);
749         }
750         else
751         {
752             SendMessage(hwndSSCombo,
753                         CB_SETCURSEL,
754                         0,
755                         0);
756         }
757 
758         HeapFree(GetProcessHeap(),
759                  0,
760                  lpCurSs);
761     }
762     else
763     {
764         /* Set screensaver to (none) */
765         SendMessage(hwndSSCombo,
766                     CB_SETCURSEL,
767                     0,
768                     0);
769     }
770 
771     /* Set the current timeout */
772     lpCurSs = GetCurrentScreenSaverValue(_T("ScreenSaveTimeOut"));
773     if (lpCurSs)
774     {
775         UINT Time = _ttoi(lpCurSs);
776 
777         Time /= 60;
778 
779         SendDlgItemMessage(hwndDlg,
780                            IDC_SCREENS_TIME,
781                            UDM_SETPOS32,
782                            0,
783                            Time);
784 
785         HeapFree(GetProcessHeap(),
786                  0,
787                  lpCurSs);
788 
789     }
790 
791     SelectionChanged(hwndDlg,
792                      pData);
793 
794     return TRUE;
795 }
796 
797 
798 INT_PTR CALLBACK
799 ScreenSaverPageProc(HWND hwndDlg,
800                     UINT uMsg,
801                     WPARAM wParam,
802                     LPARAM lParam)
803 {
804     PDATA pData;
805 
806     pData = (PDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
807 
808     switch (uMsg)
809     {
810         case WM_INITDIALOG:
811         {
812             OnInitDialog(hwndDlg, pData);
813             break;
814         }
815 
816         case WM_DESTROY:
817         {
818             if (pData->ScreenSaverPreviewParent)
819             {
820                 SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SCREENS_PREVIEW),
821                                  GWLP_WNDPROC,
822                                  (LONG_PTR)pData->OldPreviewProc);
823                 DestroyWindow(pData->ScreenSaverPreviewParent);
824                 pData->ScreenSaverPreviewParent = NULL;
825             }
826             UnregisterClass(szPreviewWndClass, hApplet);
827             if (pData->PrevWindowPi.hProcess)
828             {
829                 TerminateProcess(pData->PrevWindowPi.hProcess, 0);
830                 CloseHandle(pData->PrevWindowPi.hProcess);
831                 CloseHandle(pData->PrevWindowPi.hThread);
832             }
833             HeapFree(GetProcessHeap(),
834                      0,
835                      pData);
836             break;
837         }
838 
839         case WM_ENDSESSION:
840         {
841             SetScreenSaverPreviewBox(hwndDlg,
842                                      pData);
843             break;
844         }
845 
846         case WM_DRAWITEM:
847         {
848             LPDRAWITEMSTRUCT lpDrawItem;
849             lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
850 
851             if (lpDrawItem->CtlID == IDC_SCREENS_PREVIEW)
852                 ShowScreenSaverPreview(lpDrawItem, pData);
853             break;
854         }
855 
856         case WM_COMMAND:
857         {
858             DWORD controlId = LOWORD(wParam);
859             DWORD command   = HIWORD(wParam);
860 
861             switch (controlId)
862             {
863                 case IDC_SCREENS_LIST:
864                 {
865                     if (HIWORD(wParam) == CBN_SELCHANGE)
866                     {
867                         SelectionChanged(hwndDlg, pData);
868                         SetScreenSaverPreviewBox(hwndDlg, pData);
869                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
870                     }
871                     break;
872                 }
873 
874                 case IDC_SCREENS_TIMEDELAY:
875                 {
876                     if (command == EN_CHANGE)
877                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
878                     break;
879                 }
880 
881                 case IDC_SCREENS_POWER_BUTTON: // Start Powercfg.Cpl
882                 {
883                     if (command == BN_CLICKED)
884                         WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl",SW_SHOWNORMAL);
885                     break;
886                 }
887 
888                 case IDC_SCREENS_TESTSC: // Screensaver Preview
889                 {
890                     if (command == BN_CLICKED)
891                     {
892                         ScreensaverPreview(hwndDlg, pData);
893                         SetScreenSaverPreviewBox(hwndDlg, pData);
894                     }
895                     break;
896                 }
897 
898                 case IDC_SCREENS_SETTINGS: // Screensaver Settings
899                 {
900                     if (command == BN_CLICKED)
901                         ScreensaverConfig(hwndDlg, pData);
902                     break;
903                 }
904 
905                 case IDC_SCREENS_USEPASSCHK: // Screensaver Is Secure
906                 {
907                     if (command == BN_CLICKED)
908                     {
909                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
910                     }
911                     break;
912                 }
913             }
914             break;
915         }
916 
917         case WM_NOTIFY:
918         {
919             LPNMHDR lpnm = (LPNMHDR)lParam;
920 
921             switch(lpnm->code)
922             {
923                 case PSN_APPLY:
924                 {
925                     SetScreenSaver(hwndDlg, pData);
926                     return TRUE;
927                 }
928 
929                 case PSN_SETACTIVE:
930                 {
931                     /* Enable screensaver preview support */
932                     SetScreenSaverPreviewBox(hwndDlg, pData);
933                     break;
934                 }
935 
936                 case PSN_KILLACTIVE:
937                 {
938                     /* Kill running preview screensaver */
939                     if (pData->PrevWindowPi.hProcess)
940                     {
941                         TerminateProcess(pData->PrevWindowPi.hProcess, 0);
942                         CloseHandle(pData->PrevWindowPi.hProcess);
943                         CloseHandle(pData->PrevWindowPi.hThread);
944                         pData->PrevWindowPi.hThread = pData->PrevWindowPi.hProcess = NULL;
945                     }
946                     break;
947                 }
948             }
949         }
950         break;
951     }
952 
953     return FALSE;
954 }
955