/* Copyright (C) 2009 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include "display_setting.h" #include "vdlog.h" enum DisplaySettingFlags { DISPLAY_SETTING_FLAGS_DISABLE_WALLPAPER = (1 << 0), DISPLAY_SETTING_FLAGS_DISABLE_FONT_SMOOTH = (1 << 1), DISPLAY_SETTING_FLAGS_DISABLE_ANIMATION = (1 << 2), }; #define DISPLAY_SETTING_MASK_REG_VALUE "DisplaySettingMask" #define USER_DESKTOP_REGISTRY_KEY "Control Panel\\Desktop" void DisplaySetting::set(DisplaySettingOptions& opts) { HKEY hkey; DWORD dispos; LSTATUS status; BYTE reg_mask = 0; vd_printf("setting display options"); if (opts._disable_wallpaper) { reg_mask |= DISPLAY_SETTING_FLAGS_DISABLE_WALLPAPER; } if (opts._disable_font_smoothing) { reg_mask |= DISPLAY_SETTING_FLAGS_DISABLE_FONT_SMOOTH; } if (opts._disable_animation) { reg_mask |= DISPLAY_SETTING_FLAGS_DISABLE_ANIMATION; } status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, _reg_key.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dispos); if (status != ERROR_SUCCESS) { vd_printf("create/open registry key: fail %lu", GetLastError()); } else { status = RegSetValueExA(hkey, DISPLAY_SETTING_MASK_REG_VALUE, 0, REG_BINARY, ®_mask, sizeof(reg_mask)); if (status != ERROR_SUCCESS) { vd_printf("setting registry key DisplaySettingMask: fail %lu", GetLastError()); } RegCloseKey(hkey); } load(opts); } void DisplaySetting::load() { LSTATUS status; HKEY hkey; DWORD value_type; DWORD value_size; BYTE setting_mask; DisplaySettingOptions display_opts; vd_printf("loading display setting"); status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, _reg_key.c_str(), 0, KEY_READ, &hkey); if (status != ERROR_SUCCESS) { vd_printf("open registry key: fail %lu", status); return; } value_size = sizeof(setting_mask); status = RegQueryValueExA(hkey, DISPLAY_SETTING_MASK_REG_VALUE, NULL, &value_type, &setting_mask, &value_size); if (status != ERROR_SUCCESS) { vd_printf("get registry mask value: fail %lu", GetLastError()); RegCloseKey(hkey); return; } RegCloseKey(hkey); if (value_type != REG_BINARY) { vd_printf("get registry mask value: bad value type %lu", value_type); return; } if (setting_mask & DISPLAY_SETTING_FLAGS_DISABLE_WALLPAPER) { display_opts._disable_wallpaper = true; } if (setting_mask & DISPLAY_SETTING_FLAGS_DISABLE_FONT_SMOOTH) { display_opts._disable_font_smoothing = true; } if (setting_mask & DISPLAY_SETTING_FLAGS_DISABLE_ANIMATION) { display_opts._disable_animation = true; } load(display_opts); } // returns 0 if failes DWORD DisplaySetting::get_user_process_id() { PROCESSENTRY32 proc_entry; DWORD explorer_pid = 0; DWORD agent_session_id; if (!ProcessIdToSessionId(GetCurrentProcessId(), &agent_session_id)) { vd_printf("ProcessIdToSessionId for current process failed %lu", GetLastError()); return 0; } HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snap == INVALID_HANDLE_VALUE) { vd_printf("CreateToolhelp32Snapshot() failed %lu", GetLastError()); return 0; } ZeroMemory(&proc_entry, sizeof(proc_entry)); proc_entry.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(snap, &proc_entry)) { vd_printf("Process32First() failed %lu", GetLastError()); CloseHandle(snap); return 0; } do { if (_tcsicmp(proc_entry.szExeFile, TEXT("explorer.exe")) == 0) { DWORD explorer_session_id; if (!ProcessIdToSessionId(proc_entry.th32ProcessID, &explorer_session_id)) { vd_printf("ProcessIdToSessionId for explorer failed %lu", GetLastError()); break; } if (explorer_session_id == agent_session_id) { explorer_pid = proc_entry.th32ProcessID; break; } } } while (Process32Next(snap, &proc_entry)); CloseHandle(snap); if (explorer_pid == 0) { vd_printf("explorer.exe not found"); return 0; } return explorer_pid; } bool DisplaySetting::load(DisplaySettingOptions& opts) { bool need_reload = false; bool ret = true; if (opts._disable_wallpaper) { ret &= disable_wallpaper(); } else { need_reload = true; } if (opts._disable_font_smoothing) { ret &= disable_font_smoothing(); } else { need_reload = true; } if (opts._disable_animation) { ret &= disable_animation(); } else { need_reload = true; } if (need_reload) { ret &= reload_from_registry(opts); } return ret; } bool DisplaySetting::reload_from_registry(DisplaySettingOptions& opts) { DWORD user_pid; HANDLE hprocess, htoken; bool ret = true; user_pid = get_user_process_id(); if (!user_pid) { vd_printf("get_user_process_id failed"); return false; } else { vd_printf("explorer pid %ld", user_pid); } hprocess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, user_pid); if (!OpenProcessToken(hprocess, TOKEN_ALL_ACCESS, &htoken)) { vd_printf("OpenProcessToken: failed %lu", GetLastError()); CloseHandle(hprocess); return false; } HKEY hkey_cur_user = NULL; HKEY hkey_desktop = NULL; LONG status; try { ImpersonateLoggedOnUser(htoken); status = RegOpenCurrentUser(KEY_READ, &hkey_cur_user); if (status != ERROR_SUCCESS) { vd_printf("RegOpenCurrentUser: failed %lu", GetLastError()); throw; } status = RegOpenKeyExA(hkey_cur_user, USER_DESKTOP_REGISTRY_KEY, 0, KEY_READ, &hkey_desktop); if (status != ERROR_SUCCESS) { vd_printf("RegOpenKeyExA: failed %lu", GetLastError()); throw; } if (!opts._disable_wallpaper) { ret &= reload_wallpaper(hkey_desktop); } if (!opts._disable_font_smoothing) { ret &= reload_font_smoothing(hkey_desktop); } if (!opts._disable_animation) { ret &= reload_animation(hkey_desktop); } RegCloseKey(hkey_desktop); RegCloseKey(hkey_cur_user); RevertToSelf(); CloseHandle(htoken); CloseHandle(hprocess); } catch(...) { if (hkey_desktop) { RegCloseKey(hkey_desktop); } if (hkey_cur_user) { RegCloseKey(hkey_cur_user); } RevertToSelf(); CloseHandle(htoken); CloseHandle(hprocess); return false; } return ret; } bool DisplaySetting::disable_wallpaper() { if (SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, (void*)"", 0)) { vd_printf("disable wallpaper: success"); return true; } else { vd_printf("disable wallpaper: fail %lu", GetLastError()); return false; } } bool DisplaySetting::reload_wallpaper(HKEY desktop_reg_key) { TCHAR wallpaper_path[MAX_PATH + 1]; DWORD value_size = sizeof(wallpaper_path) - sizeof(wallpaper_path[0]); DWORD value_type; LONG status; TCHAR cur_wallpaper[MAX_PATH + 1]; vd_printf(""); status = RegQueryValueEx(desktop_reg_key, TEXT("Wallpaper"), NULL, &value_type, (LPBYTE)wallpaper_path, &value_size); if (status != ERROR_SUCCESS) { vd_printf("RegQueryValueEx(Wallpaper) : fail %ld", status); return false; } if (value_type != REG_SZ) { vd_printf("bad wallpaper value type %lu (expected REG_SZ)", value_type); return false; } value_size /= sizeof(wallpaper_path[0]); if (!value_size || wallpaper_path[value_size - 1] != '\0') { wallpaper_path[value_size] = '\0'; } if (SystemParametersInfo(SPI_GETDESKWALLPAPER, SPICE_N_ELEMENTS(cur_wallpaper), cur_wallpaper, 0)) { if (_tcscmp(cur_wallpaper, TEXT("")) != 0) { vd_printf("wallpaper wasn't disabled"); return true; } } else { vd_printf("SPI_GETDESKWALLPAPER failed"); } if (SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, wallpaper_path, 0)) { vd_printf("reload wallpaper: success"); return true; } else { vd_printf("reload wallpaper: failed %lu", GetLastError()); return false; } } bool DisplaySetting::disable_font_smoothing() { if (SystemParametersInfoA(SPI_SETFONTSMOOTHING, FALSE, NULL, 0)) { vd_printf("disable font smoothing: success"); return true; } else { vd_printf("disable font smoothing: fail %lu", GetLastError()); return false; } } bool DisplaySetting::reload_font_smoothing(HKEY desktop_reg_key) { CHAR smooth_value[4]; DWORD value_size = sizeof(smooth_value)-1; DWORD value_type; LONG status; BOOL cur_font_smooth; vd_printf(""); status = RegQueryValueExA(desktop_reg_key, "FontSmoothing", NULL, &value_type, (LPBYTE)smooth_value, &value_size); if (status != ERROR_SUCCESS) { vd_printf("RegQueryValueEx(FontSmoothing) : fail %ld", status); return false; } if (value_type != REG_SZ) { vd_printf("bad font smoothing value type %lu (expected REG_SZ)", value_type); return false; } if (!value_size || smooth_value[value_size - 1] != '\0') { smooth_value[value_size] = '\0'; } if (strcmp(smooth_value, "0") == 0) { vd_printf("font smoothing is disabled in registry. do nothing"); return true; } else if (strcmp(smooth_value, "2") != 0) { vd_printf("unexpectd font smoothing value %s", smooth_value); return false; } if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &cur_font_smooth, 0)) { if (cur_font_smooth) { vd_printf("font smoothing value didn't change"); return true; } } else { vd_printf("SPI_GETFONTSMOOTHING failed"); } if (SystemParametersInfo(SPI_SETFONTSMOOTHING, TRUE, NULL, 0)) { vd_printf("reload font smoothing: success"); return true; } else { vd_printf("reload font smoothing: failed %lu", GetLastError()); return false; } } bool DisplaySetting::disable_animation() { ANIMATIONINFO win_animation; bool ret = true; ret &= set_bool_system_parameter_info(SPI_SETUIEFFECTS, FALSE); win_animation.cbSize = sizeof(ANIMATIONINFO); win_animation.iMinAnimate = 0; if (SystemParametersInfoA(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &win_animation, 0)) { vd_printf("disable window animation: success"); } else { vd_printf("disable window animation: fail %lu", GetLastError()); ret = false; } return ret; } bool DisplaySetting::reload_win_animation(HKEY desktop_reg_key) { HKEY win_metrics_hkey; CHAR win_anim_value[4]; DWORD value_size = sizeof(win_anim_value)-1; DWORD value_type; LONG status; ANIMATIONINFO active_win_animation; vd_printf(""); status = RegOpenKeyExA(desktop_reg_key, "WindowMetrics", 0, KEY_READ, &win_metrics_hkey); if (status != ERROR_SUCCESS) { vd_printf("RegOpenKeyExA(WindowMetrics) : fail %ld", status); return false; } status = RegQueryValueExA(win_metrics_hkey, "MinAnimate", NULL, &value_type, (LPBYTE)win_anim_value, &value_size); if (status != ERROR_SUCCESS) { vd_printf("RegQueryValueEx(MinAnimate) : fail %ld", status); RegCloseKey(win_metrics_hkey); return false; } RegCloseKey(win_metrics_hkey); if (value_type != REG_SZ) { vd_printf("bad MinAnimate value type %lu (expected REG_SZ)", value_type); return false; } if (!value_size || win_anim_value[value_size - 1] != '\0') { win_anim_value[value_size] = '\0'; } if (!strcmp(win_anim_value, "0")) { vd_printf("window animation is disabled in registry. do nothing"); return true; } else if (strcmp(win_anim_value, "1") != 0) { vd_printf("unexpectd window animation value %s", win_anim_value); return false; } active_win_animation.cbSize = sizeof(ANIMATIONINFO); active_win_animation.iMinAnimate = 1; if (SystemParametersInfoA(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &active_win_animation, 0)) { vd_printf("reload window animation: success"); return false; } else { vd_printf("reload window animation: fail %lu", GetLastError()); return false; } } bool DisplaySetting::set_bool_system_parameter_info(int action, BOOL param) { if (!SystemParametersInfo(action, 0, (PVOID)(uintptr_t)param, 0)) { vd_printf("SystemParametersInfo %d: failed %lu", action, GetLastError()); return false; } return true; } bool DisplaySetting::reload_ui_effects(HKEY desktop_reg_key) { DWORD ui_mask[2]; // one DWORD in xp, two DWORD in Windows 7 DWORD value_size = sizeof(ui_mask); DWORD value_type; LONG status; bool ret = true; vd_printf(""); status = RegQueryValueExA(desktop_reg_key, "UserPreferencesMask", NULL, &value_type, (LPBYTE)&ui_mask, &value_size); if (status != ERROR_SUCCESS) { vd_printf("RegQueryValueEx(UserPreferencesMask) : fail %ld", status); return false; } if (value_type != REG_BINARY) { vd_printf("bad UserPreferencesMask value type %lu (expected REG_BINARY)", value_type); return false; } vd_printf("UserPreferencesMask = %lx %lx", ui_mask[0], ui_mask[1]); ret &= set_bool_system_parameter_info(SPI_SETUIEFFECTS, ui_mask[0] & 0x80000000); ret &= set_bool_system_parameter_info(SPI_SETACTIVEWINDOWTRACKING, ui_mask[0] & 0x01); ret &= set_bool_system_parameter_info(SPI_SETMENUANIMATION, ui_mask[0] & 0x02); ret &= set_bool_system_parameter_info(SPI_SETCOMBOBOXANIMATION, ui_mask[0] & 0x04); ret &= set_bool_system_parameter_info(SPI_SETLISTBOXSMOOTHSCROLLING, ui_mask[0] & 0x08); ret &= set_bool_system_parameter_info(SPI_SETGRADIENTCAPTIONS, ui_mask[0] & 0x10); ret &= set_bool_system_parameter_info(SPI_SETKEYBOARDCUES, ui_mask[0] & 0x20); ret &= set_bool_system_parameter_info(SPI_SETACTIVEWNDTRKZORDER, ui_mask[0] & 0x40); ret &= set_bool_system_parameter_info(SPI_SETHOTTRACKING, ui_mask[0] & 0x80); ret &= set_bool_system_parameter_info(SPI_SETMENUFADE, ui_mask[0] & 0x200); ret &= set_bool_system_parameter_info(SPI_SETSELECTIONFADE, ui_mask[0] & 0x400); ret &= set_bool_system_parameter_info(SPI_SETTOOLTIPANIMATION, ui_mask[0] & 0x800); ret &= set_bool_system_parameter_info(SPI_SETTOOLTIPFADE, ui_mask[0] & 0x1000); ret &= set_bool_system_parameter_info(SPI_SETCURSORSHADOW, ui_mask[0] & 0x2000); return true; } bool DisplaySetting::reload_animation(HKEY desktop_reg_key) { bool ret = true; vd_printf(""); ret &= reload_win_animation(desktop_reg_key); ret &= reload_ui_effects(desktop_reg_key); return ret; }