/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Display Control Panel * FILE: dll/cpl/desk/desk.c * PURPOSE: ReactOS Display Control Panel * * PROGRAMMERS: Trevor McCort (lycan359@gmail.com) */ #include "desk.h" #include #include #include #define NDEBUG #include /* Enable this for InstallScreenSaverW() to determine a possible full path * to the specified screensaver file, verify its existence and use it. * (NOTE: This is not Windows desk.cpl-compatible.) */ // #define CHECK_SCR_FULL_PATH VOID WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow); static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ThemesPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK BackgroundPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ScreenSaverPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK SettingsPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); UINT CALLBACK SettingsPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp); HINSTANCE hApplet = NULL; HWND hCPLWindow = NULL; /* Applets */ APPLET Applets[] = { { IDC_DESK_ICON, IDS_CPLNAME, IDS_CPLDESCRIPTION, DisplayApplet } }; HMENU LoadPopupMenu(IN HINSTANCE hInstance, IN LPCTSTR lpMenuName) { HMENU hMenu, hSubMenu = NULL; hMenu = LoadMenu(hInstance, lpMenuName); if (hMenu != NULL) { hSubMenu = GetSubMenu(hMenu, 0); if (hSubMenu != NULL && !RemoveMenu(hMenu, 0, MF_BYPOSITION)) { hSubMenu = NULL; } DestroyMenu(hMenu); } return hSubMenu; } static BOOL CALLBACK DisplayAppletPropSheetAddPage(HPROPSHEETPAGE hpage, LPARAM lParam) { PROPSHEETHEADER *ppsh = (PROPSHEETHEADER *)lParam; if (ppsh != NULL && ppsh->nPages < MAX_DESK_PAGES) { ppsh->phpage[ppsh->nPages++] = hpage; return TRUE; } return FALSE; } static BOOL InitPropSheetPage(PROPSHEETHEADER *ppsh, WORD idDlg, DLGPROC DlgProc, LPFNPSPCALLBACK pfnCallback) { HPROPSHEETPAGE hPage; PROPSHEETPAGE psp; if (ppsh->nPages < MAX_DESK_PAGES) { ZeroMemory(&psp, sizeof(psp)); psp.dwSize = sizeof(psp); psp.dwFlags = PSP_DEFAULT; if (pfnCallback != NULL) psp.dwFlags |= PSP_USECALLBACK; psp.hInstance = hApplet; psp.pszTemplate = MAKEINTRESOURCE(idDlg); psp.pfnDlgProc = DlgProc; psp.pfnCallback = pfnCallback; hPage = CreatePropertySheetPage(&psp); if (hPage != NULL) { return DisplayAppletPropSheetAddPage(hPage, (LPARAM)ppsh); } } return FALSE; } static const struct { WORD idDlg; DLGPROC DlgProc; LPFNPSPCALLBACK Callback; LPWSTR Name; } PropPages[] = { /* { IDD_THEMES, ThemesPageProc, NULL, L"Themes" }, */ /* TODO: */ { IDD_BACKGROUND, BackgroundPageProc, NULL, L"Desktop" }, { IDD_SCREENSAVER, ScreenSaverPageProc, NULL, L"Screen Saver" }, { IDD_APPEARANCE, AppearancePageProc, NULL, L"Appearance" }, { IDD_SETTINGS, SettingsPageProc, SettingsPageCallbackProc, L"Settings" }, }; static int CALLBACK PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM lParam) { // NOTE: This callback is needed to set large icon correctly. HICON hIcon; switch (uMsg) { case PSCB_INITIALIZED: { hIcon = LoadIconW(hApplet, MAKEINTRESOURCEW(IDC_DESK_ICON)); SendMessageW(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon); break; } } return 0; } /* Display Applet */ static LONG APIENTRY DisplayApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam) { HPROPSHEETPAGE hpsp[MAX_DESK_PAGES]; PROPSHEETHEADER psh; HPSXA hpsxa = NULL; UINT i; LPWSTR *argv = NULL; LPCWSTR pwszSelectedTab = NULL; LPCWSTR pwszFile = NULL; LPCWSTR pwszAction = NULL; INT nPage = 0; BITMAP bitmap; UNREFERENCED_PARAMETER(wParam); hCPLWindow = hwnd; if (uMsg == CPL_STARTWPARMSW && lParam) { int argc; int i; nPage = _wtoi((PWSTR)lParam); #if 0 argv = CommandLineToArgvW((LPCWSTR)lParam, &argc); #else argv = CommandLineToArgvW(GetCommandLineW(), &argc); #endif if (argv && argc) { for (i = 0; ilData = 0; CPlInfo->idIcon = Applets[i].idIcon; CPlInfo->idName = Applets[i].idName; CPlInfo->idInfo = Applets[i].idDescription; } else { return TRUE; } break; case CPL_DBLCLK: if (i < _countof(Applets)) Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); else return TRUE; break; case CPL_STARTWPARMSW: if (i < _countof(Applets)) return Applets[i].AppletProc(hwndCPl, uMsg, lParam1, lParam2); break; } return FALSE; } void WINAPI InstallScreenSaverW( IN HWND hWindow, IN HANDLE hInstance, IN LPCWSTR pszFile, IN UINT nCmdShow) { LRESULT rc; HKEY regKey; INT Timeout; #ifdef CHECK_SCR_FULL_PATH HANDLE hFile; WIN32_FIND_DATAW fdFile; #endif DWORD dwLen; WCHAR szFullPath[MAX_PATH]; if (!pszFile) { DPRINT1("InstallScreenSaver() null file\n"); SetLastError(ERROR_INVALID_PARAMETER); return; } DPRINT("InstallScreenSaver() Installing screensaver %ls\n", pszFile); #ifdef CHECK_SCR_FULL_PATH /* Retrieve the actual path to the file and verify whether it exists */ dwLen = GetFullPathNameW(pszFile, _countof(szFullPath), szFullPath, NULL); if (dwLen == 0 || dwLen > _countof(szFullPath)) { DPRINT1("InstallScreenSaver() File %ls not accessible\n", pszFile); return; } hFile = FindFirstFile(szFullPath, &fdFile); if (hFile == INVALID_HANDLE_VALUE) { DPRINT1("InstallScreenSaver() File %ls not found\n", pszFile); return; } FindClose(hFile); /* Use the full file path from now on */ pszFile = szFullPath; #endif rc = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_SET_VALUE, ®Key); if (rc == ERROR_SUCCESS) { /* Set the screensaver */ SIZE_T Length = (wcslen(pszFile) + 1) * sizeof(WCHAR); rc = RegSetValueExW(regKey, L"SCRNSAVE.EXE", 0, REG_SZ, (PBYTE)pszFile, (DWORD)Length); RegCloseKey(regKey); } if (rc != ERROR_SUCCESS) { DPRINT1("InstallScreenSaver() Could not change the current screensaver\n"); return; } SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, TRUE, 0, SPIF_UPDATEINIFILE); /* If no screensaver timeout is present, default to 10 minutes (600 seconds) */ Timeout = 0; if (!SystemParametersInfoW(SPI_GETSCREENSAVETIMEOUT, 0, &Timeout, 0) || (Timeout <= 0)) SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT, 600, 0, SPIF_UPDATEINIFILE); /* Retrieve the name of this current instance of desk.cpl */ dwLen = GetModuleFileNameW(hApplet, szFullPath, _countof(szFullPath)); if ((dwLen == 0) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { /* We failed, copy the default value */ StringCchCopyW(szFullPath, _countof(szFullPath), L"desk.cpl"); } /* Build the desk.cpl command-line to start the ScreenSaver page. * Equivalent to: "desk.cpl,ScreenSaver,@ScreenSaver" */ rc = StringCchCatW(szFullPath, _countof(szFullPath), L",,1"); if (FAILED(rc)) return; /* Open the ScreenSaver page in this desk.cpl instance */ DPRINT("InstallScreenSaver() Starting '%ls'\n", szFullPath); Control_RunDLLW(hWindow, hInstance, szFullPath, nCmdShow); } void WINAPI InstallScreenSaverA( IN HWND hWindow, IN HANDLE hInstance, IN LPCSTR pszFile, IN UINT nCmdShow) { LPWSTR lpwString; int nLength; if (!pszFile) { DPRINT1("InstallScreenSaver() null file\n"); SetLastError(ERROR_INVALID_PARAMETER); return; } /* Convert the string to unicode */ lpwString = NULL; nLength = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0); if (nLength != 0) { lpwString = LocalAlloc(LMEM_FIXED, nLength * sizeof(WCHAR)); if (lpwString) { if (!MultiByteToWideChar(CP_ACP, 0, pszFile, -1, lpwString, nLength)) { LocalFree(lpwString); lpwString = NULL; } } } if (!lpwString) { DPRINT1("InstallScreenSaver() not enough memory to convert string to unicode\n"); return; } /* Call the unicode function */ InstallScreenSaverW(hWindow, hInstance, lpwString, nCmdShow); LocalFree(lpwString); } BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID lpvReserved) { UNREFERENCED_PARAMETER(lpvReserved); switch (dwReason) { case DLL_PROCESS_ATTACH: CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); RegisterPreviewControl(hInstDLL); // case DLL_THREAD_ATTACH: hApplet = hInstDLL; break; case DLL_PROCESS_DETACH: UnregisterPreviewControl(hInstDLL); CoUninitialize(); break; } return TRUE; }