You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CleanDesktop.cxx 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /* 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. // -=- CleanDesktop.cxx
  19. #define WIN32_LEAN_AND_MEAN
  20. #include <windows.h>
  21. #include <wininet.h>
  22. #include <shlobj.h>
  23. #include <rfb_win32/CleanDesktop.h>
  24. #include <rfb_win32/CurrentUser.h>
  25. #include <rfb_win32/Registry.h>
  26. #include <rfb/LogWriter.h>
  27. #include <rdr/Exception.h>
  28. using namespace rfb;
  29. using namespace rfb::win32;
  30. static LogWriter vlog("CleanDesktop");
  31. struct ActiveDesktop {
  32. ActiveDesktop() : handle(0) {
  33. // - Contact Active Desktop
  34. HRESULT result = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,
  35. IID_IActiveDesktop, (PVOID*)&handle);
  36. if (result != S_OK)
  37. throw rdr::SystemException("failed to contact Active Desktop", result);
  38. }
  39. ~ActiveDesktop() {
  40. if (handle)
  41. handle->Release();
  42. }
  43. bool enable(bool enable_) {
  44. // - Get the current Active Desktop options
  45. COMPONENTSOPT adOptions;
  46. memset(&adOptions, 0, sizeof(adOptions));
  47. adOptions.dwSize = sizeof(adOptions);
  48. HRESULT result = handle->GetDesktopItemOptions(&adOptions, 0);
  49. if (result != S_OK) {
  50. vlog.error("failed to get Active Desktop options: %d", result);
  51. return false;
  52. }
  53. // - If Active Desktop is active, disable it
  54. if ((adOptions.fActiveDesktop==0) != (enable_==0)) {
  55. if (enable_)
  56. vlog.debug("enabling Active Desktop");
  57. else
  58. vlog.debug("disabling Active Desktop");
  59. adOptions.fActiveDesktop = enable_;
  60. result = handle->SetDesktopItemOptions(&adOptions, 0);
  61. if (result != S_OK) {
  62. vlog.error("failed to disable ActiveDesktop: %d", result);
  63. return false;
  64. }
  65. handle->ApplyChanges(AD_APPLY_REFRESH);
  66. return true;
  67. }
  68. return false;
  69. }
  70. IActiveDesktop* handle;
  71. };
  72. DWORD SysParamsInfo(UINT action, UINT param, PVOID ptr, UINT ini) {
  73. DWORD r = ERROR_SUCCESS;
  74. if (!SystemParametersInfo(action, param, ptr, ini)) {
  75. r = GetLastError();
  76. vlog.info("SPI error: %d", r);
  77. }
  78. return r;
  79. }
  80. CleanDesktop::CleanDesktop() : restoreActiveDesktop(false), restoreWallpaper(false), restoreEffects(false) {
  81. CoInitialize(0);
  82. }
  83. CleanDesktop::~CleanDesktop() {
  84. enableEffects();
  85. enablePattern();
  86. enableWallpaper();
  87. CoUninitialize();
  88. }
  89. void CleanDesktop::disableWallpaper() {
  90. try {
  91. ImpersonateCurrentUser icu;
  92. vlog.debug("disable desktop wallpaper/Active Desktop");
  93. // -=- First attempt to remove the wallpaper using Active Desktop
  94. try {
  95. ActiveDesktop ad;
  96. if (ad.enable(false))
  97. restoreActiveDesktop = true;
  98. } catch (rdr::Exception& e) {
  99. vlog.error(e.str());
  100. }
  101. // -=- Switch of normal wallpaper and notify apps
  102. SysParamsInfo(SPI_SETDESKWALLPAPER, 0, "", SPIF_SENDCHANGE);
  103. restoreWallpaper = true;
  104. } catch (rdr::Exception& e) {
  105. vlog.info(e.str());
  106. }
  107. }
  108. void CleanDesktop::enableWallpaper() {
  109. try {
  110. ImpersonateCurrentUser icu;
  111. if (restoreActiveDesktop) {
  112. vlog.debug("restore Active Desktop");
  113. // -=- First attempt to re-enable Active Desktop
  114. try {
  115. ActiveDesktop ad;
  116. ad.enable(true);
  117. restoreActiveDesktop = false;
  118. } catch (rdr::Exception& e) {
  119. vlog.error(e.str());
  120. }
  121. }
  122. if (restoreWallpaper) {
  123. vlog.debug("restore desktop wallpaper");
  124. // -=- Then restore the standard wallpaper if required
  125. SysParamsInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);
  126. restoreWallpaper = false;
  127. }
  128. } catch (rdr::Exception& e) {
  129. vlog.info(e.str());
  130. }
  131. }
  132. void CleanDesktop::disablePattern() {
  133. try {
  134. ImpersonateCurrentUser icu;
  135. vlog.debug("disable desktop pattern");
  136. SysParamsInfo(SPI_SETDESKPATTERN, 0, "", SPIF_SENDCHANGE);
  137. restorePattern = true;
  138. } catch (rdr::Exception& e) {
  139. vlog.info(e.str());
  140. }
  141. }
  142. void CleanDesktop::enablePattern() {
  143. try {
  144. if (restorePattern) {
  145. ImpersonateCurrentUser icu;
  146. vlog.debug("restoring pattern...");
  147. TCharArray pattern;
  148. if (osVersion.isPlatformWindows) {
  149. RegKey cfgKey;
  150. cfgKey.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
  151. pattern.buf = cfgKey.getString(_T("Pattern"));
  152. }
  153. SysParamsInfo(SPI_SETDESKPATTERN, 0, pattern.buf, SPIF_SENDCHANGE);
  154. restorePattern = false;
  155. }
  156. } catch (rdr::Exception& e) {
  157. vlog.info(e.str());
  158. }
  159. }
  160. void CleanDesktop::disableEffects() {
  161. #if (WINVER >= 0x500)
  162. try {
  163. ImpersonateCurrentUser icu;
  164. vlog.debug("disable desktop effects");
  165. SysParamsInfo(SPI_SETFONTSMOOTHING, FALSE, 0, SPIF_SENDCHANGE);
  166. if (SysParamsInfo(SPI_GETUIEFFECTS, 0, &uiEffects, 0) == ERROR_CALL_NOT_IMPLEMENTED) {
  167. SysParamsInfo(SPI_GETCOMBOBOXANIMATION, 0, &comboBoxAnim, 0);
  168. SysParamsInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradientCaptions, 0);
  169. SysParamsInfo(SPI_GETHOTTRACKING, 0, &hotTracking, 0);
  170. SysParamsInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &listBoxSmoothScroll, 0);
  171. SysParamsInfo(SPI_GETMENUANIMATION, 0, &menuAnim, 0);
  172. SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, FALSE, SPIF_SENDCHANGE);
  173. SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, FALSE, SPIF_SENDCHANGE);
  174. SysParamsInfo(SPI_SETHOTTRACKING, 0, FALSE, SPIF_SENDCHANGE);
  175. SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, FALSE, SPIF_SENDCHANGE);
  176. SysParamsInfo(SPI_SETMENUANIMATION, 0, FALSE, SPIF_SENDCHANGE);
  177. } else {
  178. SysParamsInfo(SPI_SETUIEFFECTS, 0, FALSE, SPIF_SENDCHANGE);
  179. }
  180. restoreEffects = true;
  181. } catch (rdr::Exception& e) {
  182. vlog.info(e.str());
  183. }
  184. #else
  185. vlog.info("disableffects not implemented");
  186. #endif
  187. }
  188. void CleanDesktop::enableEffects() {
  189. try {
  190. if (restoreEffects) {
  191. #if (WINVER >= 0x500)
  192. ImpersonateCurrentUser icu;
  193. vlog.debug("restore desktop effects");
  194. RegKey desktopCfg;
  195. desktopCfg.openKey(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"));
  196. SysParamsInfo(SPI_SETFONTSMOOTHING, desktopCfg.getInt(_T("FontSmoothing"), 0) != 0, 0, SPIF_SENDCHANGE);
  197. if (SysParamsInfo(SPI_SETUIEFFECTS, 0, (void*)uiEffects, SPIF_SENDCHANGE) == ERROR_CALL_NOT_IMPLEMENTED) {
  198. SysParamsInfo(SPI_SETCOMBOBOXANIMATION, 0, (void*)comboBoxAnim, SPIF_SENDCHANGE);
  199. SysParamsInfo(SPI_SETGRADIENTCAPTIONS, 0, (void*)gradientCaptions, SPIF_SENDCHANGE);
  200. SysParamsInfo(SPI_SETHOTTRACKING, 0, (void*)hotTracking, SPIF_SENDCHANGE);
  201. SysParamsInfo(SPI_SETLISTBOXSMOOTHSCROLLING, 0, (void*)listBoxSmoothScroll, SPIF_SENDCHANGE);
  202. SysParamsInfo(SPI_SETMENUANIMATION, 0, (void*)menuAnim, SPIF_SENDCHANGE);
  203. }
  204. restoreEffects = false;
  205. #else
  206. vlog.info("enableEffects not implemented");
  207. #endif
  208. }
  209. } catch (rdr::Exception& e) {
  210. vlog.info(e.str());
  211. }
  212. }