blob: 9fb8347816699817c8670cdc483bb6417a259ea4 [file] [log] [blame]
Constantin Kaplinsky47ed8d32004-10-08 09:43:57 +00001/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19// -=- CleanDesktop.cxx
20
21#define WIN32_LEAN_AND_MEAN
22#include <windows.h>
23#include <wininet.h>
24#include <shlobj.h>
25
26#include <rfb_win32/CleanDesktop.h>
27#include <rfb_win32/CurrentUser.h>
28#include <rfb_win32/Registry.h>
29#include <rfb/LogWriter.h>
30#include <rdr/Exception.h>
31
32using namespace rfb;
33using namespace rfb::win32;
34
35static LogWriter vlog("CleanDesktop");
36
37
38struct ActiveDesktop {
39 ActiveDesktop() : handle(0) {
40 // - Contact Active Desktop
41 HRESULT result = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,
42 IID_IActiveDesktop, (PVOID*)&handle);
43 if (result != S_OK)
44 throw rdr::SystemException("failed to contact Active Desktop", result);
45 }
46 ~ActiveDesktop() {
47 if (handle)
48 handle->Release();
49 }
50 bool enable(bool enable_) {
51 // - Get the current Active Desktop options
52 COMPONENTSOPT adOptions;
53 memset(&adOptions, 0, sizeof(adOptions));
54 adOptions.dwSize = sizeof(adOptions);
55
56 HRESULT result = handle->GetDesktopItemOptions(&adOptions, 0);
57 if (result != S_OK) {
58 vlog.error("failed to get Active Desktop options: %d", result);
59 return false;
60 }
61
62 // - If Active Desktop is active, disable it
63 if ((adOptions.fActiveDesktop==0) != (enable_==0)) {
64 if (enable_)
65 vlog.debug("enabling Active Desktop");
66 else
67 vlog.debug("disabling Active Desktop");
68
69 adOptions.fActiveDesktop = enable_;
70 result = handle->SetDesktopItemOptions(&adOptions, 0);
71 if (result != S_OK) {
72 vlog.error("failed to disable ActiveDesktop: %d", result);
73 return false;
74 }
75 handle->ApplyChanges(AD_APPLY_REFRESH);
76 return true;
77 }
78 return false;
79 }
80 IActiveDesktop* handle;
81};
82
83
84DWORD SysParamsInfo(UINT action, UINT param, PVOID ptr, UINT ini) {
85 DWORD r = ERROR_SUCCESS;
86 if (!SystemParametersInfo(action, param, ptr, ini)) {
87 r = GetLastError();
88 vlog.info("SPI error: %d", r);
89 }
90 return r;
91}
92
93
94CleanDesktop::CleanDesktop() : restoreActiveDesktop(false), restoreWallpaper(false), restoreEffects(false) {
95 CoInitialize(0);
96}
97
98CleanDesktop::~CleanDesktop() {
99 enableEffects();
100 enablePattern();
101 enableWallpaper();
102 CoUninitialize();
103}
104
105void CleanDesktop::disableWallpaper() {
106 try {
107 ImpersonateCurrentUser icu;
108
109 vlog.debug("disable desktop wallpaper/Active Desktop");
110
111 // -=- First attempt to remove the wallpaper using Active Desktop
112 try {
113 ActiveDesktop ad;
114 if (ad.enable(false))
115 restoreActiveDesktop = true;
116 } catch (rdr::Exception& e) {
117 vlog.error(e.str());
118 }
119
120 // -=- Switch of normal wallpaper and notify apps
121 SysParamsInfo(SPI_SETDESKWALLPAPER, 0, "", SPIF_SENDCHANGE);
122 restoreWallpaper = true;
123
124 } catch (rdr::Exception& e) {
125 vlog.info(e.str());
126 }
127}
128
129void CleanDesktop::enableWallpaper() {
130 try {
131 ImpersonateCurrentUser icu;
132
133 if (restoreActiveDesktop) {
134 vlog.debug("restore Active Desktop");
135
136 // -=- First attempt to re-enable Active Desktop
137 try {
138 ActiveDesktop ad;
139 ad.enable(true);
140 restoreActiveDesktop = false;
141 } catch (rdr::Exception& e) {
142 vlog.error(e.str());
143 }
144 }
145
146 if (restoreWallpaper) {
147 vlog.debug("restore desktop wallpaper");
148
149 // -=- Then restore the standard wallpaper if required
150 SysParamsInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);
151 restoreWallpaper = false;
152 }
153
154 } catch (rdr::Exception& e) {
155 vlog.info(e.str());
156 }
157}
158
159
160void CleanDesktop::disablePattern() {
161 try {
162 ImpersonateCurrentUser icu;
163
164 vlog.debug("disable desktop pattern");
165 SysParamsInfo(SPI_SETDESKPATTERN, 0, "", SPIF_SENDCHANGE);
166 restorePattern = true;
167
168 } catch (rdr::Exception& e) {
169 vlog.info(e.str());
170 }
171}
172
173void CleanDesktop::enablePattern() {
174 try {
175 if (restorePattern) {
176 ImpersonateCurrentUser icu;
177
178 vlog.debug("restoring pattern...");
179
180 TCharArray pattern;
181 if (osVersion.isPlatformWindows) {
182 RegKey cfgKey;
183 cfgKey.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
184 pattern.buf = cfgKey.getString(_T("Pattern"));
185 }
186 SysParamsInfo(SPI_SETDESKPATTERN, 0, pattern.buf, SPIF_SENDCHANGE);
187 restorePattern = false;
188 }
189
190 } catch (rdr::Exception& e) {
191 vlog.info(e.str());
192 }
193}
194
195
196void CleanDesktop::disableEffects() {
197#if (WINVER >= 0x500)
198 try {
199 ImpersonateCurrentUser icu;
200
201 vlog.debug("disable desktop effects");
202
203 SysParamsInfo(SPI_SETFONTSMOOTHING, FALSE, 0, SPIF_SENDCHANGE);
204 if (SysParamsInfo(SPI_GETUIEFFECTS, 0, &uiEffects, 0) == ERROR_CALL_NOT_IMPLEMENTED) {
205 SysParamsInfo(SPI_GETCOMBOBOXANIMATION, 0, &comboBoxAnim, 0);
206 SysParamsInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradientCaptions, 0);
207 SysParamsInfo(SPI_GETHOTTRACKING, 0, &hotTracking, 0);
208 SysParamsInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &listBoxSmoothScroll, 0);
209 SysParamsInfo(SPI_GETMENUANIMATION, 0, &menuAnim, 0);
210 SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, FALSE, SPIF_SENDCHANGE);
211 SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, FALSE, SPIF_SENDCHANGE);
212 SysParamsInfo(SPI_SETHOTTRACKING, 0, FALSE, SPIF_SENDCHANGE);
213 SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, FALSE, SPIF_SENDCHANGE);
214 SysParamsInfo(SPI_SETMENUANIMATION, 0, FALSE, SPIF_SENDCHANGE);
215 } else {
216 SysParamsInfo(SPI_SETUIEFFECTS, 0, FALSE, SPIF_SENDCHANGE);
217 }
218 restoreEffects = true;
219
220 } catch (rdr::Exception& e) {
221 vlog.info(e.str());
222 }
223#else
224 vlog.info("disableffects not implemented");
225#endif
226}
227
228void CleanDesktop::enableEffects() {
229 try {
230 if (restoreEffects) {
231#if (WINVER >= 0x500)
232 ImpersonateCurrentUser icu;
233
234 vlog.debug("restore desktop effects");
235
236 RegKey desktopCfg;
237 desktopCfg.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
238 SysParamsInfo(SPI_SETFONTSMOOTHING, desktopCfg.getInt(_T("FontSmoothing"), 0) != 0, 0, SPIF_SENDCHANGE);
239 if (SysParamsInfo(SPI_SETUIEFFECTS, 0, (void*)uiEffects, SPIF_SENDCHANGE) == ERROR_CALL_NOT_IMPLEMENTED) {
240 SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, (void*)comboBoxAnim, SPIF_SENDCHANGE);
241 SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, (void*)gradientCaptions, SPIF_SENDCHANGE);
242 SysParamsInfo(SPI_SETHOTTRACKING, 0, (void*)hotTracking, SPIF_SENDCHANGE);
243 SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (void*)listBoxSmoothScroll, SPIF_SENDCHANGE);
244 SysParamsInfo(SPI_SETMENUANIMATION, 0, (void*)menuAnim, SPIF_SENDCHANGE);
245 }
246 restoreEffects = false;
247#else
248 vlog.info("enableEffects not implemented");
249#endif
250 }
251
252 } catch (rdr::Exception& e) {
253 vlog.info(e.str());
254 }
255}