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