Index: remoting/host/sas_injector_win.cc |
diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3dd55f1cf32f6c09ef6ec298c7a8a21e2fba5bbe |
--- /dev/null |
+++ b/remoting/host/sas_injector_win.cc |
@@ -0,0 +1,186 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "remoting/host/sas_injector.h" |
+ |
+#include <windows.h> |
+#include <string> |
+ |
+#include "base/logging.h" |
+#include "base/file_path.h" |
+#include "base/native_library.h" |
+#include "base/path_service.h" |
+#include "base/utf_string_conversions.h" |
+#include "base/win/registry.h" |
+#include "base/win/windows_version.h" |
+ |
+namespace remoting { |
+ |
+namespace { |
+ |
+// Names of the API and library implementing software SAS generation. |
+const FilePath::CharType kSasDllFileName[] = |
+ FILE_PATH_LITERAL("sas.dll"); |
+const char kSendSasName[] = "SendSAS"; |
+ |
+// The prototype of SendSAS(). |
+typedef VOID (WINAPI *SendSasFunc)(BOOL); |
+ |
+// The registry key and value holding the policy controlling software SAS |
+// generation. |
+const char kSystemPolicyKeyName[] = |
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; |
+const char kSoftwareSasValueName[] = "SoftwareSASGeneration"; |
+ |
+const DWORD kEnableSoftwareSasByServices = 1; |
+ |
+// Toggles the default software SAS generation policy to enable SAS generation |
+// by services. Non-default policy is not changed. |
+class ScopedSoftwareSasPolicy { |
+ public: |
+ ScopedSoftwareSasPolicy(); |
+ ~ScopedSoftwareSasPolicy(); |
+ |
+ bool Apply(); |
+ |
+ private: |
+ // The handle of the registry key were SoftwareSASGeneration policy is stored. |
+ base::win::RegKey system_policy_; |
+ |
+ // Name of the registry value holding the policy. |
+ string16 value_name_; |
+ |
+ // True if the policy needs to be restored. |
+ bool restore_policy_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedSoftwareSasPolicy); |
+}; |
+ |
+ScopedSoftwareSasPolicy::ScopedSoftwareSasPolicy() |
+ : restore_policy_(false) { |
+} |
+ |
+ScopedSoftwareSasPolicy::~ScopedSoftwareSasPolicy() { |
+ // Restore the default policy by deleting the value that we have set. |
+ if (restore_policy_) { |
+ LONG result = system_policy_.DeleteValue(value_name_.c_str()); |
+ if (result != ERROR_SUCCESS) { |
+ SetLastError(result); |
+ LOG_GETLASTERROR(ERROR) |
+ << "Failed to restore the software SAS generation policy"; |
+ } |
+ } |
+} |
+ |
+bool ScopedSoftwareSasPolicy::Apply() { |
+ // Query the currently set SoftwareSASGeneration policy. |
+ LONG result = system_policy_.Open(HKEY_LOCAL_MACHINE, |
+ ASCIIToUTF16(kSystemPolicyKeyName).c_str(), |
+ KEY_QUERY_VALUE | KEY_SET_VALUE | |
+ KEY_WOW64_64KEY); |
+ if (result != ERROR_SUCCESS) { |
+ SetLastError(result); |
+ LOG_GETLASTERROR(ERROR) << "Failed to open 'HKLM\\" |
+ << kSystemPolicyKeyName << "'"; |
+ return false; |
+ } |
+ |
+ value_name_ = ASCIIToUTF16(kSoftwareSasValueName); |
+ bool custom_policy = system_policy_.HasValue(value_name_.c_str()); |
+ |
+ // Override the default policy (i.e. there is no value in the registry) only. |
+ if (!custom_policy) { |
+ result = system_policy_.WriteValue(value_name_.c_str(), |
+ kEnableSoftwareSasByServices); |
+ if (result != ERROR_SUCCESS) { |
+ SetLastError(result); |
+ LOG_GETLASTERROR(ERROR) |
+ << "Failed to enable software SAS generation by services"; |
+ return false; |
+ } else { |
+ restore_policy_ = true; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+} // namespace |
+ |
+// Sends the Secure Attention Sequence using the SendSAS() function from |
+// sas.dll. This library is shipped starting from Win7/W2K8 R2 only. However |
+// Win7 SDK includes a redistributable verion of the same library that works on |
+// Vista/W2K8. We install the latter along with our binaries. |
+class SasInjectorWin : public SasInjector { |
+ public: |
+ SasInjectorWin(); |
+ virtual ~SasInjectorWin(); |
+ |
+ // SasInjector implementation. |
+ virtual bool InjectSas() OVERRIDE; |
+ |
+ private: |
+ base::NativeLibrary sas_dll_; |
+ SendSasFunc send_sas_; |
+}; |
+ |
+SasInjectorWin::SasInjectorWin() : sas_dll_(NULL), send_sas_(NULL) { |
+} |
+ |
+SasInjectorWin::~SasInjectorWin() { |
+ if (sas_dll_ != NULL) { |
+ base::UnloadNativeLibrary(sas_dll_); |
+ } |
+} |
+ |
+bool SasInjectorWin::InjectSas() { |
+ // Load sas.dll. The library is expected to be in the same folder as this |
+ // binary. |
+ if (sas_dll_ == NULL) { |
+ FilePath exe_path; |
+ if (!PathService::Get(base::FILE_EXE, &exe_path)) { |
+ LOG(ERROR) << "Failed to get the executable file name."; |
+ return false; |
+ } |
+ |
+ std::string error; |
+ sas_dll_ = base::LoadNativeLibrary( |
+ exe_path.DirName().Append(kSasDllFileName), |
+ &error); |
+ if (sas_dll_ == NULL) { |
+ LOG(ERROR) << "Failed to load '" << kSasDllFileName << "'"; |
+ return false; |
+ } |
+ } |
+ |
+ // Get the pointer to sas!SendSAS(). |
+ if (send_sas_ == NULL) { |
+ send_sas_ = reinterpret_cast<SendSasFunc>( |
+ base::GetFunctionPointerFromNativeLibrary(sas_dll_, kSendSasName)); |
+ if (send_sas_ == NULL) { |
+ LOG(ERROR) << "Failed to retrieve the address of '" << kSendSasName |
+ << "()'"; |
+ return false; |
+ } |
+ } |
+ |
+ // Enable software SAS generation by services and send SAS. SAS can still fail |
+ // if the policy does not allow services to generate software SAS. |
+ ScopedSoftwareSasPolicy enable_sas; |
+ if (!enable_sas.Apply()) |
+ return false; |
+ |
+ (*send_sas_)(FALSE); |
+ return true; |
+} |
+ |
+scoped_ptr<SasInjector> SasInjector::Create() { |
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) { |
+ return scoped_ptr<SasInjector>(new SasInjectorWin()); |
+ } |
+ |
+ return scoped_ptr<SasInjector>(); |
+} |
+ |
+} // namespace remoting |