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
,
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
);
188 ScreensaverConfig(HWND hwndDlg
, PDATA pData
)
191 /c:<hwnd> Run configuration, hwnd is handle of calling window
194 TCHAR szCmdline
[2048];
196 PROCESS_INFORMATION pi
;
198 if (pData
->Selection
< 1)
203 pData
->ScreenSaverItems
[pData
->Selection
].szFilename
,
206 ZeroMemory(&si
, sizeof(si
));
208 ZeroMemory(&pi
, sizeof(pi
));
209 if(CreateProcess(NULL
,
220 /* Kill off the previous preview process */
221 if (pData
->PrevWindowPi
.hProcess
)
223 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
224 CloseHandle(pData
->PrevWindowPi
.hProcess
);
225 CloseHandle(pData
->PrevWindowPi
.hThread
);
226 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
229 if (WaitForSettingsDialog(hwndDlg
, pi
.hProcess
))
230 SetScreenSaverPreviewBox(hwndDlg
, pData
);
236 ScreensaverPreview(HWND hwndDlg
, PDATA pData
)
242 TCHAR szCmdline
[2048];
244 PROCESS_INFORMATION pi
;
246 if (pData
->Selection
< 1)
249 /* Kill off the previous preview process */
250 if (pData
->PrevWindowPi
.hProcess
)
252 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
253 CloseHandle(pData
->PrevWindowPi
.hProcess
);
254 CloseHandle(pData
->PrevWindowPi
.hThread
);
255 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;
260 pData
->ScreenSaverItems
[pData
->Selection
].szFilename
);
262 ZeroMemory(&si
, sizeof(si
));
264 ZeroMemory(&pi
, sizeof(pi
));
265 if(CreateProcess(NULL
,
276 WaitForSingleObject(pi
.hProcess
, INFINITE
);
277 CloseHandle(pi
.hProcess
);
278 CloseHandle(pi
.hThread
);
284 CheckRegScreenSaverIsSecure(HWND hwndDlg
)
288 DWORD bufferSize
= sizeof(szBuffer
);
289 DWORD varType
= REG_SZ
;
292 if (RegOpenKeyEx(HKEY_CURRENT_USER
,
293 _T("Control Panel\\Desktop"),
296 &hKey
) == ERROR_SUCCESS
)
298 result
= RegQueryValueEx(hKey
,
299 _T("ScreenSaverIsSecure"),
306 if (result
== ERROR_SUCCESS
)
308 if (_ttoi(szBuffer
) == 1)
310 SendDlgItemMessage(hwndDlg
,
311 IDC_SCREENS_USEPASSCHK
,
319 SendDlgItemMessage(hwndDlg
,
320 IDC_SCREENS_USEPASSCHK
,
322 (WPARAM
)BST_UNCHECKED
,
329 SearchScreenSavers(HWND hwndScreenSavers
,
330 LPCTSTR pszSearchPath
,
334 TCHAR szSearchPath
[MAX_PATH
];
336 ScreenSaverItem
*ScreenSaverItem
;
338 UINT i
, ScreenSaverCount
;
341 ScreenSaverCount
= pData
->ScreenSaverCount
;
343 hr
= StringCbCopy(szSearchPath
, sizeof(szSearchPath
), pszSearchPath
);
346 hr
= StringCbCat(szSearchPath
, sizeof(szSearchPath
), TEXT("\\*.scr"));
350 hFind
= FindFirstFile(szSearchPath
, &fd
);
352 if (hFind
== INVALID_HANDLE_VALUE
)
355 while (ScreenSaverCount
< MAX_SCREENSAVERS
)
357 /* Don't add any hidden screensavers */
358 if ((fd
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) == 0)
360 TCHAR filename
[MAX_PATH
];
362 hr
= StringCbCopy(filename
, sizeof(filename
), pszSearchPath
);
368 hr
= StringCbCat(filename
, sizeof(filename
), _T("\\"));
374 hr
= StringCbCat(filename
, sizeof(filename
), fd
.cFileName
);
381 ScreenSaverItem
= pData
->ScreenSaverItems
+ ScreenSaverCount
;
383 ScreenSaverItem
->bIsScreenSaver
= TRUE
;
385 hModule
= LoadLibraryEx(filename
,
387 DONT_RESOLVE_DLL_REFERENCES
| LOAD_LIBRARY_AS_DATAFILE
);
390 if (0 == LoadString(hModule
,
392 ScreenSaverItem
->szDisplayName
,
393 sizeof(ScreenSaverItem
->szDisplayName
) / sizeof(TCHAR
)))
395 // If the string does not exists, copy the name of the file
396 hr
= StringCbCopy(ScreenSaverItem
->szDisplayName
, sizeof(ScreenSaverItem
->szDisplayName
), fd
.cFileName
);
399 FreeLibrary(hModule
);
403 ScreenSaverItem
->szDisplayName
[_tcslen(fd
.cFileName
)-4] = '\0';
405 FreeLibrary(hModule
);
409 hr
= StringCbCopy(ScreenSaverItem
->szDisplayName
, sizeof(ScreenSaverItem
->szDisplayName
), _T("Unknown"));
417 hr
= StringCbCopy(ScreenSaverItem
->szFilename
, sizeof(ScreenSaverItem
->szFilename
), filename
);
424 i
= SendMessage(hwndScreenSavers
,
427 (LPARAM
)ScreenSaverItem
->szDisplayName
);
429 SendMessage(hwndScreenSavers
,
432 (LPARAM
)ScreenSaverCount
);
437 if (!FindNextFile(hFind
, &fd
))
443 pData
->ScreenSaverCount
= ScreenSaverCount
;
448 AddScreenSavers(HWND hwndDlg
, PDATA pData
)
450 HWND hwndScreenSavers
= GetDlgItem(hwndDlg
, IDC_SCREENS_LIST
);
451 TCHAR szSearchPath
[MAX_PATH
];
452 TCHAR szLocalPath
[MAX_PATH
];
454 ScreenSaverItem
*ScreenSaverItem
= NULL
;
457 /* Add the "None" item */
458 ScreenSaverItem
= pData
->ScreenSaverItems
;
460 ScreenSaverItem
->bIsScreenSaver
= FALSE
;
464 ScreenSaverItem
->szDisplayName
,
465 sizeof(ScreenSaverItem
->szDisplayName
) / sizeof(TCHAR
));
467 i
= SendMessage(hwndScreenSavers
,
470 (LPARAM
)ScreenSaverItem
->szDisplayName
);
472 SendMessage(hwndScreenSavers
,
477 // Initialize number of items into the list
478 pData
->ScreenSaverCount
= 1;
480 // Add all the screensavers where the applet is stored.
481 GetModuleFileName(hApplet
, szLocalPath
, MAX_PATH
);
482 lpBackSlash
= _tcsrchr(szLocalPath
, _T('\\'));
483 if (lpBackSlash
!= NULL
)
486 SearchScreenSavers(hwndScreenSavers
, szLocalPath
, pData
);
489 // Add all the screensavers in the C:\ReactOS\System32 directory.
490 GetSystemDirectory(szSearchPath
, MAX_PATH
);
491 if (lpBackSlash
!= NULL
&& _tcsicmp(szSearchPath
, szLocalPath
) != 0)
492 SearchScreenSavers(hwndScreenSavers
, szSearchPath
, pData
);
494 // Add all the screensavers in the C:\ReactOS directory.
495 GetWindowsDirectory(szSearchPath
, MAX_PATH
);
496 if (lpBackSlash
!= NULL
&& _tcsicmp(szSearchPath
, szLocalPath
) != 0)
497 SearchScreenSavers(hwndScreenSavers
, szSearchPath
, pData
);
502 SetScreenSaver(HWND hwndDlg
, PDATA pData
)
505 BOOL DeleteMode
= FALSE
;
507 DBG_UNREFERENCED_LOCAL_VARIABLE(DeleteMode
);
509 if (RegOpenKeyEx(HKEY_CURRENT_USER
,
510 _T("Control Panel\\Desktop"),
513 ®Key
) == ERROR_SUCCESS
)
520 /* Set the screensaver */
521 if (pData
->ScreenSaverItems
[pData
->Selection
].bIsScreenSaver
)
523 RegSetValueEx(regKey
,
527 (PBYTE
)pData
->ScreenSaverItems
[pData
->Selection
].szFilename
,
528 _tcslen(pData
->ScreenSaverItems
[pData
->Selection
].szFilename
) * sizeof(TCHAR
));
530 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE
, TRUE
, 0, SPIF_UPDATEINIFILE
);
534 /* Windows deletes the value if no screensaver is set */
535 RegDeleteValue(regKey
, _T("SCRNSAVE.EXE"));
538 SystemParametersInfo(SPI_SETSCREENSAVEACTIVE
, FALSE
, 0, SPIF_UPDATEINIFILE
);
541 /* Set the secure value */
542 Ret
= SendDlgItemMessage(hwndDlg
,
543 IDC_SCREENS_USEPASSCHK
,
547 Sec
= (Ret
== BST_CHECKED
) ? _T('1') : _T('0');
548 RegSetValueEx(regKey
,
549 _T("ScreenSaverIsSecure"),
555 /* Set the screensaver time delay */
556 Time
= GetDlgItemInt(hwndDlg
,
557 IDC_SCREENS_TIMEDELAY
,
565 SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT
, Time
, 0, SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
573 OnInitDialog(HWND hwndDlg
, PDATA pData
)
576 HWND hwndSSCombo
= GetDlgItem(hwndDlg
, IDC_SCREENS_LIST
);
579 pData
= HeapAlloc(GetProcessHeap(),
584 EndDialog(hwndDlg
, -1);
588 SetWindowLongPtr(hwndDlg
,
592 pData
->Selection
= -1;
594 SendDlgItemMessage(hwndDlg
,
599 ((short) 240, (short) 1));
601 AddScreenSavers(hwndDlg
,
604 CheckRegScreenSaverIsSecure(hwndDlg
);
606 /* Set the current screensaver in the combo box */
607 lpCurSs
= GetCurrentScreenSaverValue(_T("SCRNSAVE.EXE"));
613 for (i
= 0; i
< MAX_SCREENSAVERS
; i
++)
615 if (!_tcscmp(lpCurSs
, pData
->ScreenSaverItems
[i
].szFilename
))
624 Num
= SendMessage(hwndSSCombo
,
627 (LPARAM
)pData
->ScreenSaverItems
[i
].szDisplayName
);
629 SendMessage(hwndSSCombo
,
636 SendMessage(hwndSSCombo
,
642 HeapFree(GetProcessHeap(),
648 /* Set screensaver to (none) */
649 SendMessage(hwndSSCombo
,
655 /* Set the current timeout */
656 lpCurSs
= GetCurrentScreenSaverValue(_T("ScreenSaveTimeOut"));
659 UINT Time
= _ttoi(lpCurSs
);
663 SendDlgItemMessage(hwndDlg
,
669 HeapFree(GetProcessHeap(),
675 SelectionChanged(hwndDlg
,
683 ScreenSaverPageProc(HWND hwndDlg
,
690 pData
= (PDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
696 OnInitDialog(hwndDlg
, pData
);
702 if (pData
->PrevWindowPi
.hProcess
)
704 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
705 CloseHandle(pData
->PrevWindowPi
.hProcess
);
706 CloseHandle(pData
->PrevWindowPi
.hThread
);
708 HeapFree(GetProcessHeap(),
716 SetScreenSaverPreviewBox(hwndDlg
,
723 DWORD controlId
= LOWORD(wParam
);
724 DWORD command
= HIWORD(wParam
);
728 case IDC_SCREENS_LIST
:
730 if (HIWORD(wParam
) == CBN_SELCHANGE
)
732 SelectionChanged(hwndDlg
, pData
);
733 SetScreenSaverPreviewBox(hwndDlg
, pData
);
734 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
739 case IDC_SCREENS_TIMEDELAY
:
741 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
745 case IDC_SCREENS_POWER_BUTTON
: // Start Powercfg.Cpl
747 if (command
== BN_CLICKED
)
748 WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl",SW_SHOWNORMAL
);
752 case IDC_SCREENS_TESTSC
: // Screensaver Preview
754 if(command
== BN_CLICKED
)
756 ScreensaverPreview(hwndDlg
, pData
);
757 SetScreenSaverPreviewBox(hwndDlg
, pData
);
762 case IDC_SCREENS_SETTINGS
: // Screensaver Settings
764 if (command
== BN_CLICKED
)
765 ScreensaverConfig(hwndDlg
, pData
);
769 case IDC_SCREENS_USEPASSCHK
: // Screensaver Is Secure
771 if (command
== BN_CLICKED
)
773 PropSheet_Changed(GetParent(hwndDlg
), hwndDlg
);
783 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
789 SetScreenSaver(hwndDlg
, pData
);
795 /* Enable screensaver preview support */
796 SetScreenSaverPreviewBox(hwndDlg
, pData
);
802 /* Kill running preview screensaver */
803 if (pData
->PrevWindowPi
.hProcess
)
805 TerminateProcess(pData
->PrevWindowPi
.hProcess
, 0);
806 CloseHandle(pData
->PrevWindowPi
.hProcess
);
807 CloseHandle(pData
->PrevWindowPi
.hThread
);
808 pData
->PrevWindowPi
.hThread
= pData
->PrevWindowPi
.hProcess
= NULL
;