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
7 * PROGRAMMERS: Trevor McCort (lycan359@gmail.com)
8 * Ged Murphy (gedmurphy@reactos.org)
13 #define MAX_SCREENSAVERS 100
17 BOOL bIsScreenSaver
; /* Is this background a wallpaper */
18 TCHAR szFilename
[MAX_PATH
];
19 TCHAR szDisplayName
[256];
25 ScreenSaverItem ScreenSaverItems
[MAX_SCREENSAVERS
];
26 PROCESS_INFORMATION PrevWindowPi
;
28 UINT ScreenSaverCount
;
33 GetCurrentScreenSaverValue(LPTSTR lpValue
)
37 DWORD BufSize
, Type
= REG_SZ
;
40 Ret
= RegOpenKeyEx(HKEY_CURRENT_USER
,
41 _T("Control Panel\\Desktop"),
45 if (Ret
!= ERROR_SUCCESS
)
48 Ret
= RegQueryValueEx(hKey
,
54 if (Ret
== ERROR_SUCCESS
)
56 lpBuf
= HeapAlloc(GetProcessHeap(),
61 Ret
= RegQueryValueEx(hKey
,
67 if (Ret
!= ERROR_SUCCESS
)
69 HeapFree(GetProcessHeap(), 0, lpBuf
);
82 SelectionChanged(HWND hwndDlg
, PDATA pData
)
88 hwndCombo
= GetDlgItem(hwndDlg
, IDC_SCREENS_LIST
);
90 i
= (INT
)SendMessage(hwndCombo
, CB_GETCURSEL
, 0, 0);
91 i
= (INT
)SendMessage(hwndCombo
, CB_GETITEMDATA
, i
, 0);
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
);
108 SetScreenSaverPreviewBox(HWND hwndDlg
, PDATA pData
)
110 HWND hPreview
= GetDlgItem(hwndDlg
, IDC_SCREENS_PREVIEW
);
112 TCHAR szCmdline
[2048];
114 /* Kill off the previous preview process */
115 if (pData
->PrevWindowPi
.hProcess
)
117 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
118 CloseHandle(pData
->PrevWindowPi
.hProcess
);
119 CloseHandle(pData
->PrevWindowPi
.hThread
);
120 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
123 if (pData
->Selection
> 0)
127 pData
->ScreenSaverItems
[pData
->Selection
].szFilename
,
128 (ULONG_PTR
)hPreview
);
130 ZeroMemory(&si
, sizeof(si
));
132 ZeroMemory(&pData
->PrevWindowPi
, sizeof(pData
->PrevWindowPi
));
134 if (!CreateProcess(NULL
,
143 &pData
->PrevWindowPi
))
145 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
151 WaitForSettingsDialog(HWND hwndDlg
,
159 dwResult
= MsgWaitForMultipleObjects(1,
164 if (dwResult
== WAIT_OBJECT_0
+ 1)
166 if (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
168 if (msg
.message
== WM_QUIT
)
172 if (IsDialogMessage(hwndDlg
, &msg
))
174 TranslateMessage(&msg
);
175 DispatchMessage(&msg
);
183 else if (dwResult
== WAIT_OBJECT_0
)
196 ScreensaverConfig(HWND hwndDlg
, PDATA pData
)
199 * /c:<hwnd> Run configuration, hwnd is handle of calling window
202 TCHAR szCmdline
[2048];
204 PROCESS_INFORMATION pi
;
206 if (pData
->Selection
< 1)
211 pData
->ScreenSaverItems
[pData
->Selection
].szFilename
,
214 ZeroMemory(&si
, sizeof(si
));
216 ZeroMemory(&pi
, sizeof(pi
));
217 if (CreateProcess(NULL
,
228 /* Kill off the previous preview process */
229 if (pData
->PrevWindowPi
.hProcess
)
231 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
232 CloseHandle(pData
->PrevWindowPi
.hProcess
);
233 CloseHandle(pData
->PrevWindowPi
.hThread
);
234 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
237 if (WaitForSettingsDialog(hwndDlg
, pi
.hProcess
))
238 SetScreenSaverPreviewBox(hwndDlg
, pData
);
244 ScreensaverPreview(HWND hwndDlg
, PDATA pData
)
250 TCHAR szCmdline
[2048];
252 PROCESS_INFORMATION pi
;
254 if (pData
->Selection
< 1)
257 /* Kill off the previous preview process */
258 if (pData
->PrevWindowPi
.hProcess
)
260 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
261 CloseHandle(pData
->PrevWindowPi
.hProcess
);
262 CloseHandle(pData
->PrevWindowPi
.hThread
);
263 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
268 pData
->ScreenSaverItems
[pData
->Selection
].szFilename
);
270 ZeroMemory(&si
, sizeof(si
));
272 ZeroMemory(&pi
, sizeof(pi
));
273 if (CreateProcess(NULL
,
284 WaitForSingleObject(pi
.hProcess
, INFINITE
);
285 CloseHandle(pi
.hProcess
);
286 CloseHandle(pi
.hThread
);
292 CheckRegScreenSaverIsSecure(HWND hwndDlg
)
296 DWORD bufferSize
= sizeof(szBuffer
);
297 DWORD varType
= REG_SZ
;
300 if (RegOpenKeyEx(HKEY_CURRENT_USER
,
301 _T("Control Panel\\Desktop"),
304 &hKey
) == ERROR_SUCCESS
)
306 result
= RegQueryValueEx(hKey
,
307 _T("ScreenSaverIsSecure"),
314 if (result
== ERROR_SUCCESS
)
316 if (_ttoi(szBuffer
) == 1)
318 SendDlgItemMessage(hwndDlg
,
319 IDC_SCREENS_USEPASSCHK
,
327 SendDlgItemMessage(hwndDlg
,
328 IDC_SCREENS_USEPASSCHK
,
330 (WPARAM
)BST_UNCHECKED
,
337 SearchScreenSavers(HWND hwndScreenSavers
,
338 LPCTSTR pszSearchPath
,
342 TCHAR szSearchPath
[MAX_PATH
];
344 ScreenSaverItem
*ScreenSaverItem
;
346 UINT i
, ScreenSaverCount
;
349 ScreenSaverCount
= pData
->ScreenSaverCount
;
351 hr
= StringCbCopy(szSearchPath
, sizeof(szSearchPath
), pszSearchPath
);
354 hr
= StringCbCat(szSearchPath
, sizeof(szSearchPath
), TEXT("\\*.scr"));
358 hFind
= FindFirstFile(szSearchPath
, &fd
);
360 if (hFind
== INVALID_HANDLE_VALUE
)
363 while (ScreenSaverCount
< MAX_SCREENSAVERS
)
365 /* Don't add any hidden screensavers */
366 if ((fd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) == 0)
368 TCHAR filename
[MAX_PATH
];
370 hr
= StringCbCopy(filename
, sizeof(filename
), pszSearchPath
);
376 hr
= StringCbCat(filename
, sizeof(filename
), _T("\\"));
382 hr
= StringCbCat(filename
, sizeof(filename
), fd
.cFileName
);
389 ScreenSaverItem
= pData
->ScreenSaverItems
+ ScreenSaverCount
;
391 ScreenSaverItem
->bIsScreenSaver
= TRUE
;
393 hModule
= LoadLibraryEx(filename
,
395 DONT_RESOLVE_DLL_REFERENCES
| LOAD_LIBRARY_AS_DATAFILE
);
398 if (0 == LoadString(hModule
,
400 ScreenSaverItem
->szDisplayName
,
401 sizeof(ScreenSaverItem
->szDisplayName
) / sizeof(TCHAR
)))
403 // If the string does not exists, copy the name of the file
404 hr
= StringCbCopy(ScreenSaverItem
->szDisplayName
, sizeof(ScreenSaverItem
->szDisplayName
), fd
.cFileName
);
407 FreeLibrary(hModule
);
411 ScreenSaverItem
->szDisplayName
[_tcslen(fd
.cFileName
)-4] = '\0';
413 FreeLibrary(hModule
);
417 hr
= StringCbCopy(ScreenSaverItem
->szDisplayName
, sizeof(ScreenSaverItem
->szDisplayName
), _T("Unknown"));
425 hr
= StringCbCopy(ScreenSaverItem
->szFilename
, sizeof(ScreenSaverItem
->szFilename
), filename
);
432 i
= SendMessage(hwndScreenSavers
,
435 (LPARAM
)ScreenSaverItem
->szDisplayName
);
437 SendMessage(hwndScreenSavers
,
440 (LPARAM
)ScreenSaverCount
);
445 if (!FindNextFile(hFind
, &fd
))
451 pData
->ScreenSaverCount
= ScreenSaverCount
;
456 AddScreenSavers(HWND hwndDlg
, PDATA pData
)
458 HWND hwndScreenSavers
= GetDlgItem(hwndDlg
, IDC_SCREENS_LIST
);
459 TCHAR szSearchPath
[MAX_PATH
];
460 TCHAR szLocalPath
[MAX_PATH
];
462 ScreenSaverItem
*ScreenSaverItem
= NULL
;
465 /* Add the "None" item */
466 ScreenSaverItem
= pData
->ScreenSaverItems
;
468 ScreenSaverItem
->bIsScreenSaver
= FALSE
;
472 ScreenSaverItem
->szDisplayName
,
473 sizeof(ScreenSaverItem
->szDisplayName
) / sizeof(TCHAR
));
475 i
= SendMessage(hwndScreenSavers
,
478 (LPARAM
)ScreenSaverItem
->szDisplayName
);
480 SendMessage(hwndScreenSavers
,
485 // Initialize number of items into the list
486 pData
->ScreenSaverCount
= 1;
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
)
494 SearchScreenSavers(hwndScreenSavers
, szLocalPath
, pData
);
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
);
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
);
510 SetScreenSaver(HWND hwndDlg
, PDATA pData
)
513 BOOL DeleteMode
= FALSE
;
515 DBG_UNREFERENCED_LOCAL_VARIABLE(DeleteMode
);
517 if (RegOpenKeyEx(HKEY_CURRENT_USER
,
518 _T("Control Panel\\Desktop"),
521 ®Key
) == ERROR_SUCCESS
)
528 /* Set the screensaver */
529 if (pData
->ScreenSaverItems
[pData
->Selection
].bIsScreenSaver
)
531 SIZE_T Length
= _tcslen(pData
->ScreenSaverItems
[pData
->Selection
].szFilename
) * sizeof(TCHAR
);
532 RegSetValueEx(regKey
,
536 (PBYTE
)pData
->ScreenSaverItems
[pData
->Selection
].szFilename
,
539 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE
, TRUE
, 0, SPIF_UPDATEINIFILE
);
543 /* Windows deletes the value if no screensaver is set */
544 RegDeleteValue(regKey
, _T("SCRNSAVE.EXE"));
547 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE
, FALSE
, 0, SPIF_UPDATEINIFILE
);
550 /* Set the secure value */
551 Ret
= SendDlgItemMessage(hwndDlg
,
552 IDC_SCREENS_USEPASSCHK
,
556 Sec
= (Ret
== BST_CHECKED
) ? _T('1') : _T('0');
557 RegSetValueEx(regKey
,
558 _T("ScreenSaverIsSecure"),
564 /* Set the screensaver time delay */
565 Time
= GetDlgItemInt(hwndDlg
,
566 IDC_SCREENS_TIMEDELAY
,
574 SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT
, Time
, 0, SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
582 OnInitDialog(HWND hwndDlg
, PDATA pData
)
585 HWND hwndSSCombo
= GetDlgItem(hwndDlg
, IDC_SCREENS_LIST
);
588 pData
= HeapAlloc(GetProcessHeap(),
593 EndDialog(hwndDlg
, -1);
597 SetWindowLongPtr(hwndDlg
,
601 pData
->Selection
= -1;
603 SendDlgItemMessage(hwndDlg
,
608 ((short) 240, (short) 1));
610 AddScreenSavers(hwndDlg
,
613 CheckRegScreenSaverIsSecure(hwndDlg
);
615 /* Set the current screensaver in the combo box */
616 lpCurSs
= GetCurrentScreenSaverValue(_T("SCRNSAVE.EXE"));
622 for (i
= 0; i
< MAX_SCREENSAVERS
; i
++)
624 if (!_tcscmp(lpCurSs
, pData
->ScreenSaverItems
[i
].szFilename
))
633 Num
= SendMessage(hwndSSCombo
,
636 (LPARAM
)pData
->ScreenSaverItems
[i
].szDisplayName
);
638 SendMessage(hwndSSCombo
,
645 SendMessage(hwndSSCombo
,
651 HeapFree(GetProcessHeap(),
657 /* Set screensaver to (none) */
658 SendMessage(hwndSSCombo
,
664 /* Set the current timeout */
665 lpCurSs
= GetCurrentScreenSaverValue(_T("ScreenSaveTimeOut"));
668 UINT Time
= _ttoi(lpCurSs
);
672 SendDlgItemMessage(hwndDlg
,
678 HeapFree(GetProcessHeap(),
684 SelectionChanged(hwndDlg
,
692 ScreenSaverPageProc(HWND hwndDlg
,
699 pData
= (PDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
705 OnInitDialog(hwndDlg
, pData
);
711 if (pData
->PrevWindowPi
.hProcess
)
713 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
714 CloseHandle(pData
->PrevWindowPi
.hProcess
);
715 CloseHandle(pData
->PrevWindowPi
.hThread
);
717 HeapFree(GetProcessHeap(),
725 SetScreenSaverPreviewBox(hwndDlg
,
732 DWORD controlId
= LOWORD(wParam
);
733 DWORD command
= HIWORD(wParam
);
737 case IDC_SCREENS_LIST
:
739 if (HIWORD(wParam
) == CBN_SELCHANGE
)
741 SelectionChanged(hwndDlg
, pData
);
742 SetScreenSaverPreviewBox(hwndDlg
, pData
);
743 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
748 case IDC_SCREENS_TIMEDELAY
:
750 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
754 case IDC_SCREENS_POWER_BUTTON
: // Start Powercfg.Cpl
756 if (command
== BN_CLICKED
)
757 WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl",SW_SHOWNORMAL
);
761 case IDC_SCREENS_TESTSC
: // Screensaver Preview
763 if (command
== BN_CLICKED
)
765 ScreensaverPreview(hwndDlg
, pData
);
766 SetScreenSaverPreviewBox(hwndDlg
, pData
);
771 case IDC_SCREENS_SETTINGS
: // Screensaver Settings
773 if (command
== BN_CLICKED
)
774 ScreensaverConfig(hwndDlg
, pData
);
778 case IDC_SCREENS_USEPASSCHK
: // Screensaver Is Secure
780 if (command
== BN_CLICKED
)
782 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
792 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
798 SetScreenSaver(hwndDlg
, pData
);
804 /* Enable screensaver preview support */
805 SetScreenSaverPreviewBox(hwndDlg
, pData
);
811 /* Kill running preview screensaver */
812 if (pData
->PrevWindowPi
.hProcess
)
814 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
815 CloseHandle(pData
->PrevWindowPi
.hProcess
);
816 CloseHandle(pData
->PrevWindowPi
.hThread
);
817 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;