Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/sas_injector.h" | 5 #include "remoting/host/sas_injector.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/file_path.h" | 11 #include "base/file_path.h" |
| 12 #include "base/path_service.h" | 12 #include "base/path_service.h" |
| 13 #include "base/scoped_native_library.h" | 13 #include "base/scoped_native_library.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "base/win/registry.h" | 15 #include "base/win/registry.h" |
| 16 #include "base/win/windows_version.h" | 16 #include "base/win/windows_version.h" |
| 17 #include "remoting/host/win/desktop.h" | |
| 18 #include "remoting/host/win/scoped_thread_desktop.h" | |
| 17 | 19 |
| 18 namespace remoting { | 20 namespace remoting { |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 // Names of the API and library implementing software SAS generation. | 24 // Names of the API and library implementing software SAS generation. |
| 23 const FilePath::CharType kSasDllFileName[] = | 25 const FilePath::CharType kSasDllFileName[] = FILE_PATH_LITERAL("sas.dll"); |
| 24 FILE_PATH_LITERAL("sas.dll"); | |
| 25 const char kSendSasName[] = "SendSAS"; | 26 const char kSendSasName[] = "SendSAS"; |
| 26 | 27 |
| 27 // The prototype of SendSAS(). | 28 // The prototype of SendSAS(). |
| 28 typedef VOID (WINAPI *SendSasFunc)(BOOL); | 29 typedef VOID (WINAPI *SendSasFunc)(BOOL); |
| 29 | 30 |
| 30 // The registry key and value holding the policy controlling software SAS | 31 // The registry key and value holding the policy controlling software SAS |
| 31 // generation. | 32 // generation. |
| 32 const wchar_t kSystemPolicyKeyName[] = | 33 const wchar_t kSystemPolicyKeyName[] = |
| 33 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; | 34 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; |
| 34 const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration"; | 35 const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration"; |
| 35 | 36 |
| 36 const DWORD kEnableSoftwareSasByServices = 1; | 37 const DWORD kEnableSoftwareSasByApps = 2; |
| 37 | 38 |
| 38 // Toggles the default software SAS generation policy to enable SAS generation | 39 // Toggles the default software SAS generation policy to enable SAS generation |
| 39 // by services. Non-default policy is not changed. | 40 // by applications. Non-default policy is not changed. |
| 40 class ScopedSoftwareSasPolicy { | 41 class ScopedSoftwareSasPolicy { |
| 41 public: | 42 public: |
| 42 ScopedSoftwareSasPolicy(); | 43 ScopedSoftwareSasPolicy(); |
| 43 ~ScopedSoftwareSasPolicy(); | 44 ~ScopedSoftwareSasPolicy(); |
| 44 | 45 |
| 45 bool Apply(); | 46 bool Apply(); |
| 46 | 47 |
| 47 private: | 48 private: |
| 48 // The handle of the registry key were SoftwareSASGeneration policy is stored. | 49 // The handle of the registry key were SoftwareSASGeneration policy is stored. |
| 49 base::win::RegKey system_policy_; | 50 base::win::RegKey system_policy_; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 81 LOG_GETLASTERROR(ERROR) << "Failed to open 'HKLM\\" | 82 LOG_GETLASTERROR(ERROR) << "Failed to open 'HKLM\\" |
| 82 << kSystemPolicyKeyName << "'"; | 83 << kSystemPolicyKeyName << "'"; |
| 83 return false; | 84 return false; |
| 84 } | 85 } |
| 85 | 86 |
| 86 bool custom_policy = system_policy_.HasValue(kSoftwareSasValueName); | 87 bool custom_policy = system_policy_.HasValue(kSoftwareSasValueName); |
| 87 | 88 |
| 88 // Override the default policy (i.e. there is no value in the registry) only. | 89 // Override the default policy (i.e. there is no value in the registry) only. |
| 89 if (!custom_policy) { | 90 if (!custom_policy) { |
| 90 result = system_policy_.WriteValue(kSoftwareSasValueName, | 91 result = system_policy_.WriteValue(kSoftwareSasValueName, |
| 91 kEnableSoftwareSasByServices); | 92 kEnableSoftwareSasByApps); |
| 92 if (result != ERROR_SUCCESS) { | 93 if (result != ERROR_SUCCESS) { |
| 93 SetLastError(result); | 94 SetLastError(result); |
| 94 LOG_GETLASTERROR(ERROR) | 95 LOG_GETLASTERROR(ERROR) |
| 95 << "Failed to enable software SAS generation by services"; | 96 << "Failed to enable software SAS generation by services"; |
| 96 return false; | 97 return false; |
| 97 } else { | 98 } else { |
| 98 restore_policy_ = true; | 99 restore_policy_ = true; |
| 99 } | 100 } |
| 100 } | 101 } |
| 101 | 102 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 114 virtual ~SasInjectorWin(); | 115 virtual ~SasInjectorWin(); |
| 115 | 116 |
| 116 // SasInjector implementation. | 117 // SasInjector implementation. |
| 117 virtual bool InjectSas() OVERRIDE; | 118 virtual bool InjectSas() OVERRIDE; |
| 118 | 119 |
| 119 private: | 120 private: |
| 120 base::ScopedNativeLibrary sas_dll_; | 121 base::ScopedNativeLibrary sas_dll_; |
| 121 SendSasFunc send_sas_; | 122 SendSasFunc send_sas_; |
| 122 }; | 123 }; |
| 123 | 124 |
| 125 // Emulates Secure Attention Sequence (Ctrl+Alt+Del) by switching to | |
| 126 // the Winlogon desktop and injecting Ctrl+Alt+Del as a hot key. | |
| 127 // N.B. Windows XP/W2K3 only. | |
| 128 class SasInjectorXp : public SasInjector { | |
| 129 public: | |
| 130 SasInjectorXp(); | |
| 131 virtual ~SasInjectorXp(); | |
| 132 | |
| 133 // SasInjector implementation. | |
| 134 virtual bool InjectSas() OVERRIDE; | |
| 135 }; | |
| 136 | |
| 124 SasInjectorWin::SasInjectorWin() : send_sas_(NULL) { | 137 SasInjectorWin::SasInjectorWin() : send_sas_(NULL) { |
| 125 } | 138 } |
| 126 | 139 |
| 127 SasInjectorWin::~SasInjectorWin() { | 140 SasInjectorWin::~SasInjectorWin() { |
| 128 } | 141 } |
| 129 | 142 |
| 130 bool SasInjectorWin::InjectSas() { | 143 bool SasInjectorWin::InjectSas() { |
| 131 // Load sas.dll. The library is expected to be in the same folder as this | 144 // Load sas.dll. The library is expected to be in the same folder as this |
| 132 // binary. | 145 // binary. |
| 133 if (!sas_dll_.is_valid()) { | 146 if (!sas_dll_.is_valid()) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 150 send_sas_ = static_cast<SendSasFunc>( | 163 send_sas_ = static_cast<SendSasFunc>( |
| 151 sas_dll_.GetFunctionPointer(kSendSasName)); | 164 sas_dll_.GetFunctionPointer(kSendSasName)); |
| 152 } | 165 } |
| 153 if (send_sas_ == NULL) { | 166 if (send_sas_ == NULL) { |
| 154 LOG(ERROR) << "Failed to retrieve the address of '" << kSendSasName | 167 LOG(ERROR) << "Failed to retrieve the address of '" << kSendSasName |
| 155 << "()'"; | 168 << "()'"; |
| 156 return false; | 169 return false; |
| 157 } | 170 } |
| 158 | 171 |
| 159 // Enable software SAS generation by services and send SAS. SAS can still fail | 172 // Enable software SAS generation by services and send SAS. SAS can still fail |
| 160 // if the policy does not allow services to generate software SAS. | 173 // if the policy does not allow services to generate software SAS. |
|
simonmorris
2012/08/14 17:29:59
Does the reference to "services" need updating?
| |
| 161 ScopedSoftwareSasPolicy enable_sas; | 174 ScopedSoftwareSasPolicy enable_sas; |
| 162 if (!enable_sas.Apply()) | 175 if (!enable_sas.Apply()) |
| 163 return false; | 176 return false; |
| 164 | 177 |
| 165 (*send_sas_)(FALSE); | 178 (*send_sas_)(TRUE); |
| 179 return true; | |
| 180 } | |
| 181 | |
| 182 SasInjectorXp::SasInjectorXp() { | |
| 183 } | |
| 184 | |
| 185 SasInjectorXp::~SasInjectorXp() { | |
| 186 } | |
| 187 | |
| 188 bool SasInjectorXp::InjectSas() { | |
| 189 const wchar_t kWinlogonDesktopName[] = L"Winlogon"; | |
| 190 const wchar_t kSasWindowClassName[] = L"SAS window class"; | |
| 191 const wchar_t kSasWindowTitle[] = L"SAS window"; | |
| 192 | |
| 193 scoped_ptr<remoting::Desktop> winlogon_desktop( | |
| 194 remoting::Desktop::GetDesktop(kWinlogonDesktopName)); | |
| 195 if (!winlogon_desktop.get()) | |
| 196 return false; | |
| 197 | |
| 198 remoting::ScopedThreadDesktop desktop; | |
| 199 if (!desktop.SetThreadDesktop(winlogon_desktop.Pass())) | |
| 200 return false; | |
| 201 | |
| 202 HWND window = FindWindow(kSasWindowClassName, kSasWindowTitle); | |
| 203 if (!window) | |
| 204 return false; | |
| 205 | |
| 206 PostMessage(window, | |
| 207 WM_HOTKEY, | |
| 208 0, | |
| 209 MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); | |
| 166 return true; | 210 return true; |
| 167 } | 211 } |
| 168 | 212 |
| 169 scoped_ptr<SasInjector> SasInjector::Create() { | 213 scoped_ptr<SasInjector> SasInjector::Create() { |
| 170 if (base::win::GetVersion() >= base::win::VERSION_VISTA) { | 214 if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
| 215 return scoped_ptr<SasInjector>(new SasInjectorXp()); | |
| 216 } else { | |
| 171 return scoped_ptr<SasInjector>(new SasInjectorWin()); | 217 return scoped_ptr<SasInjector>(new SasInjectorWin()); |
| 172 } | 218 } |
| 173 | |
| 174 return scoped_ptr<SasInjector>(); | |
| 175 } | 219 } |
| 176 | 220 |
| 177 } // namespace remoting | 221 } // namespace remoting |
| OLD | NEW |