reactos/dll/cpl/desk/screensaver.c
Timo Kreuzer 6afbc8f483 Hopefully create a branch and not destroy the svn repository.
svn path=/branches/reactos-yarotows/; revision=45219
2010-01-23 23:25:04 +00:00

737 lines
20 KiB
C

/*
* 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)
{
while (TRUE)
{
DWORD Ret;
MSG msg;
while (PeekMessage(&msg,
NULL,
0,
0,
PM_REMOVE))
{
if (msg.message == WM_QUIT)
return FALSE;
if (IsDialogMessage(hwndDlg, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Ret = MsgWaitForMultipleObjects(1,
&hProcess,
FALSE,
INFINITE,
QS_ALLINPUT);
if (Ret == (WAIT_OBJECT_0))
{
return TRUE;
}
}
}
static VOID
ScreensaverConfig(HWND hwndDlg, PGLOBAL_DATA pGlobalData)
{
/*
/c:<hwnd> 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,
&regKey) == 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;
}