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