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 ®Key) == 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