/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Display Control Panel * FILE: dll/cpl/desk/screensaver.c * PURPOSE: Screen saver property page * * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) * Ged Murphy (gedmurphy@reactos.org) */ #include "desk.h" #define MAX_SCREENSAVERS 100 typedef struct { BOOL bIsScreenSaver; /* Is this background a wallpaper */ TCHAR szFilename[MAX_PATH]; TCHAR szDisplayName[256]; } ScreenSaverItem; typedef struct _GLOBAL_DATA { ScreenSaverItem ScreenSaverItems[MAX_SCREENSAVERS]; PROCESS_INFORMATION PrevWindowPi; int Selection; } GLOBAL_DATA, *PGLOBAL_DATA; static LPTSTR GetCurrentScreenSaverValue(LPTSTR lpValue) { HKEY hKey; LPTSTR lpBuf = NULL; DWORD BufSize, Type = REG_SZ; LONG Ret; Ret = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), 0, KEY_READ, &hKey); if (Ret != ERROR_SUCCESS) return NULL; Ret = RegQueryValueEx(hKey, lpValue, 0, &Type, NULL, &BufSize); if (Ret == ERROR_SUCCESS) { lpBuf = HeapAlloc(GetProcessHeap(), 0, BufSize); if (lpBuf) { Ret = RegQueryValueEx(hKey, lpValue, 0, &Type, (LPBYTE)lpBuf, &BufSize); if (Ret != ERROR_SUCCESS) lpBuf = NULL; } } RegCloseKey(hKey); return lpBuf; } static VOID SelectionChanged(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { HWND hwndCombo; BOOL bEnable; INT i; hwndCombo = GetDlgItem(hwndDlg, IDC_SCREENS_LIST); i = (INT)SendMessage(hwndCombo, CB_GETCURSEL, 0, 0); i = (INT)SendMessage(hwndCombo, CB_GETITEMDATA, i, 0); pGlobalData->Selection = i; bEnable = (i != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_SETTINGS), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TESTSC), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_USEPASSCHK), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TIMEDELAY), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_SCREENS_TIME), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_WAITTEXT), bEnable); EnableWindow(GetDlgItem(hwndDlg, IDC_MINTEXT), bEnable); } static VOID SetScreenSaverPreviewBox(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { HWND hPreview = GetDlgItem(hwndDlg, IDC_SCREENS_PREVIEW); STARTUPINFO si; TCHAR szCmdline[2048]; /* kill off the previous preview process*/ if (pGlobalData->PrevWindowPi.hProcess) { TerminateProcess(pGlobalData->PrevWindowPi.hProcess, 0); CloseHandle(pGlobalData->PrevWindowPi.hProcess); CloseHandle(pGlobalData->PrevWindowPi.hThread); pGlobalData->PrevWindowPi.hThread = pGlobalData->PrevWindowPi.hProcess = NULL; } if (pGlobalData->Selection > 0) { _stprintf(szCmdline, _T("%s /p %u"), pGlobalData->ScreenSaverItems[pGlobalData->Selection].szFilename, hPreview); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pGlobalData->PrevWindowPi, sizeof(pGlobalData->PrevWindowPi)); if (!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pGlobalData->PrevWindowPi)) { pGlobalData->PrevWindowPi.hThread = pGlobalData->PrevWindowPi.hProcess = NULL; } } } static BOOL WaitForSettingsDialog(HWND hwndDlg, HANDLE hProcess) { DWORD dwResult; MSG msg; while (TRUE) { dwResult = MsgWaitForMultipleObjects(1, &hProcess, FALSE, INFINITE, QS_ALLINPUT); if (dwResult == WAIT_OBJECT_0 + 1) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { return FALSE; } if (IsDialogMessage(hwndDlg, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } else { return TRUE; } } } static VOID ScreensaverConfig(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { /* /c: Run configuration, hwnd is handle of calling window */ TCHAR szCmdline[2048]; STARTUPINFO si; PROCESS_INFORMATION pi; if (pGlobalData->Selection < 1) return; _stprintf(szCmdline, _T("%s /c:%u"), pGlobalData->ScreenSaverItems[pGlobalData->Selection].szFilename, hwndDlg); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); if(CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { /* kill off the previous preview process */ if (pGlobalData->PrevWindowPi.hProcess) { TerminateProcess(pGlobalData->PrevWindowPi.hProcess, 0); CloseHandle(pGlobalData->PrevWindowPi.hProcess); CloseHandle(pGlobalData->PrevWindowPi.hThread); pGlobalData->PrevWindowPi.hThread = pGlobalData->PrevWindowPi.hProcess = NULL; } if (WaitForSettingsDialog(hwndDlg, pi.hProcess)) SetScreenSaverPreviewBox(hwndDlg, pGlobalData); } } static VOID ScreensaverPreview(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { /* /s Run normal */ WCHAR szCmdline[2048]; STARTUPINFO si; PROCESS_INFORMATION pi; if (pGlobalData->Selection < 1) return; /* kill off the previous preview process*/ if (pGlobalData->PrevWindowPi.hProcess) { TerminateProcess(pGlobalData->PrevWindowPi.hProcess, 0); CloseHandle(pGlobalData->PrevWindowPi.hProcess); CloseHandle(pGlobalData->PrevWindowPi.hThread); pGlobalData->PrevWindowPi.hThread = pGlobalData->PrevWindowPi.hProcess = NULL; } _stprintf(szCmdline, _T("%s /s"), pGlobalData->ScreenSaverItems[pGlobalData->Selection].szFilename); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); if(CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } } static VOID CheckRegScreenSaverIsSecure(HWND hwndDlg) { HKEY hKey; TCHAR szBuffer[2]; DWORD bufferSize = sizeof(szBuffer); DWORD varType = REG_SZ; LONG result; if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { result = RegQueryValueEx(hKey, _T("ScreenSaverIsSecure"), 0, &varType, (LPBYTE)szBuffer, &bufferSize); RegCloseKey(hKey); if (result == ERROR_SUCCESS) { if (_ttoi(szBuffer) == 1) { SendDlgItemMessage(hwndDlg, IDC_SCREENS_USEPASSCHK, BM_SETCHECK, (WPARAM)BST_CHECKED, 0); return; } } SendDlgItemMessage(hwndDlg, IDC_SCREENS_USEPASSCHK, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); } } static VOID AddScreenSavers(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { HWND hwndScreenSavers = GetDlgItem(hwndDlg, IDC_SCREENS_LIST); WIN32_FIND_DATA fd; HANDLE hFind; TCHAR szSearchPath[MAX_PATH]; INT i; int ScreenSaverCount = 0; ScreenSaverItem *ScreenSaverItem = NULL; HANDLE hModule = NULL; /* Add the "None" item */ ScreenSaverItem = &pGlobalData->ScreenSaverItems[ScreenSaverCount]; ScreenSaverItem->bIsScreenSaver = FALSE; LoadString(hApplet, IDS_NONE, ScreenSaverItem->szDisplayName, sizeof(ScreenSaverItem->szDisplayName) / sizeof(TCHAR)); i = SendMessage(hwndScreenSavers, CB_ADDSTRING, 0, (LPARAM)ScreenSaverItem->szDisplayName); SendMessage(hwndScreenSavers, CB_SETITEMDATA, i, (LPARAM)ScreenSaverCount); ScreenSaverCount++; /* Add all the screensavers in the C:\ReactOS\System32 directory. */ GetSystemDirectory(szSearchPath, MAX_PATH); _tcscat(szSearchPath, TEXT("\\*.scr")); hFind = FindFirstFile(szSearchPath, &fd); while (ScreenSaverCount < MAX_SCREENSAVERS-1 && hFind != INVALID_HANDLE_VALUE) { /* Don't add any hidden screensavers */ if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) { TCHAR filename[MAX_PATH]; GetSystemDirectory(filename, MAX_PATH); _tcscat(filename, TEXT("\\")); _tcscat(filename, fd.cFileName); ScreenSaverItem = &pGlobalData->ScreenSaverItems[ScreenSaverCount]; ScreenSaverItem->bIsScreenSaver = TRUE; hModule = LoadLibraryEx(filename, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); if (hModule) { LoadString(hModule, 1, ScreenSaverItem->szDisplayName, sizeof(ScreenSaverItem->szDisplayName) / sizeof(TCHAR)); FreeLibrary(hModule); } else { _tcscpy(ScreenSaverItem->szDisplayName, _T("Unknown")); } _tcscpy(ScreenSaverItem->szFilename, filename); i = SendMessage(hwndScreenSavers, CB_ADDSTRING, 0, (LPARAM)ScreenSaverItem->szDisplayName); SendMessage(hwndScreenSavers, CB_SETITEMDATA, i, (LPARAM)ScreenSaverCount); ScreenSaverCount++; } if (!FindNextFile(hFind, &fd)) hFind = INVALID_HANDLE_VALUE; } } static VOID SetScreenSaver(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { HKEY regKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), 0, KEY_ALL_ACCESS, ®Key) == ERROR_SUCCESS) { INT Time; BOOL bRet; TCHAR szTime[256], Sec; UINT Ret; /* set the screensaver */ if (pGlobalData->ScreenSaverItems[pGlobalData->Selection].bIsScreenSaver) { RegSetValueEx(regKey, _T("SCRNSAVE.EXE"), 0, REG_SZ, (PBYTE)pGlobalData->ScreenSaverItems[pGlobalData->Selection].szFilename, _tcslen(pGlobalData->ScreenSaverItems[pGlobalData->Selection].szFilename) * sizeof(TCHAR)); } else { /* Windows deletes the value if no screensaver is set */ RegDeleteValue(regKey, _T("SCRNSAVE.EXE")); } /* set the screensaver time delay */ Time = GetDlgItemInt(hwndDlg, IDC_SCREENS_TIMEDELAY, &bRet, FALSE); if (Time == 0) Time = 60; else Time *= 60; _itot(Time, szTime, 10); RegSetValueEx(regKey, _T("ScreenSaveTimeOut"), 0, REG_SZ, (PBYTE)szTime, _tcslen(szTime) * sizeof(TCHAR)); /* set the secure value */ Ret = SendDlgItemMessage(hwndDlg, IDC_SCREENS_USEPASSCHK, BM_GETCHECK, 0, 0); Sec = (Ret == BST_CHECKED) ? _T('1') : _T('0'); RegSetValueEx(regKey, _T("ScreenSaverIsSecure"), 0, REG_SZ, (PBYTE)&Sec, sizeof(TCHAR)); RegCloseKey(regKey); } } static BOOL OnInitDialog(HWND hwndDlg, PGLOBAL_DATA pGlobalData) { LPTSTR lpCurSs; HWND hwndSSCombo = GetDlgItem(hwndDlg, IDC_SCREENS_LIST); INT Num; pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA)); if (!pGlobalData) { EndDialog(hwndDlg, -1); return FALSE; } SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData); pGlobalData->Selection = -1; SendDlgItemMessage(hwndDlg, IDC_SCREENS_TIME, UDM_SETRANGE, 0, MAKELONG ((short) 240, (short) 1)); AddScreenSavers(hwndDlg, pGlobalData); CheckRegScreenSaverIsSecure(hwndDlg); /* set the current screensaver in the combo box */ lpCurSs = GetCurrentScreenSaverValue(_T("SCRNSAVE.EXE")); if (lpCurSs) { BOOL bFound = FALSE; INT i; for (i = 0; i < MAX_SCREENSAVERS; i++) { if (!_tcscmp(lpCurSs, pGlobalData->ScreenSaverItems[i].szFilename)) { bFound = TRUE; break; } } if (bFound) { Num = SendMessage(hwndSSCombo, CB_FINDSTRINGEXACT, -1, (LPARAM)pGlobalData->ScreenSaverItems[i].szDisplayName); if (Num != CB_ERR) SendMessage(hwndSSCombo, CB_SETCURSEL, Num, 0); } else { SendMessage(hwndSSCombo, CB_SETCURSEL, 0, 0); } HeapFree(GetProcessHeap(), 0, lpCurSs); } else { /* set screensaver to (none) */ SendMessage(hwndSSCombo, CB_SETCURSEL, 0, 0); } /* set the current timeout */ lpCurSs = GetCurrentScreenSaverValue(_T("ScreenSaveTimeOut")); if (lpCurSs) { UINT Time = _ttoi(lpCurSs); Time /= 60; SendDlgItemMessage(hwndDlg, IDC_SCREENS_TIME, UDM_SETPOS32, 0, Time); HeapFree(GetProcessHeap(), 0, lpCurSs); } SelectionChanged(hwndDlg, pGlobalData); return TRUE; } INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { PGLOBAL_DATA pGlobalData; pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { OnInitDialog(hwndDlg, pGlobalData); break; } case WM_DESTROY: { if (pGlobalData->PrevWindowPi.hProcess) { TerminateProcess(pGlobalData->PrevWindowPi.hProcess, 0); CloseHandle(pGlobalData->PrevWindowPi.hProcess); CloseHandle(pGlobalData->PrevWindowPi.hThread); } HeapFree(GetProcessHeap(), 0, pGlobalData); break; } case WM_ENDSESSION: { SetScreenSaverPreviewBox(hwndDlg, pGlobalData); break; } case WM_COMMAND: { DWORD controlId = LOWORD(wParam); DWORD command = HIWORD(wParam); switch (controlId) { case IDC_SCREENS_LIST: { if (HIWORD(wParam) == CBN_SELCHANGE) { SelectionChanged(hwndDlg, pGlobalData); SetScreenSaverPreviewBox(hwndDlg, pGlobalData); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } case IDC_SCREENS_TIMEDELAY: { PropSheet_Changed(GetParent(hwndDlg), hwndDlg); break; } case IDC_SCREENS_POWER_BUTTON: // Start Powercfg.Cpl { if (command == BN_CLICKED) WinExec("rundll32 shell32.dll,Control_RunDLL powercfg.cpl",SW_SHOWNORMAL); break; } case IDC_SCREENS_TESTSC: // Screensaver Preview { if(command == BN_CLICKED) { ScreensaverPreview(hwndDlg, pGlobalData); SetScreenSaverPreviewBox(hwndDlg, pGlobalData); } break; } case IDC_SCREENS_SETTINGS: // Screensaver Settings { if (command == BN_CLICKED) ScreensaverConfig(hwndDlg, pGlobalData); break; } case IDC_SCREENS_USEPASSCHK: // Screensaver Is Secure { if (command == BN_CLICKED) { MessageBox(NULL, TEXT("Feature not yet implemented"), TEXT("Sorry"), MB_OK); PropSheet_Changed(GetParent(hwndDlg), hwndDlg); } break; } } break; } case WM_NOTIFY: { LPNMHDR lpnm = (LPNMHDR)lParam; switch(lpnm->code) { case PSN_APPLY: { SetScreenSaver(hwndDlg, pGlobalData); return TRUE; } case PSN_SETACTIVE: { /* activate screen saver support */ SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_SENDCHANGE); SetScreenSaverPreviewBox(hwndDlg, pGlobalData); break; } case PSN_KILLACTIVE: { /* Disable screensaver support */ SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, FALSE, 0, SPIF_SENDCHANGE); if (pGlobalData->PrevWindowPi.hProcess) { TerminateProcess(pGlobalData->PrevWindowPi.hProcess, 0); CloseHandle(pGlobalData->PrevWindowPi.hProcess); CloseHandle(pGlobalData->PrevWindowPi.hThread); pGlobalData->PrevWindowPi.hThread = pGlobalData->PrevWindowPi.hProcess = NULL; } break; } } } break; } return FALSE; }