Index: remoting/host/sas_injector_win.cc |
diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc |
index 0bf453f6a69c63f6d8f7e0e7d00eceb55346561a..3e5bea80aea92cbe8ec4de0d81605ae8d416e827 100644 |
--- a/remoting/host/sas_injector_win.cc |
+++ b/remoting/host/sas_injector_win.cc |
@@ -14,14 +14,15 @@ |
#include "base/utf_string_conversions.h" |
#include "base/win/registry.h" |
#include "base/win/windows_version.h" |
+#include "remoting/host/win/desktop.h" |
+#include "remoting/host/win/scoped_thread_desktop.h" |
namespace remoting { |
namespace { |
// Names of the API and library implementing software SAS generation. |
-const FilePath::CharType kSasDllFileName[] = |
- FILE_PATH_LITERAL("sas.dll"); |
+const FilePath::CharType kSasDllFileName[] = FILE_PATH_LITERAL("sas.dll"); |
const char kSendSasName[] = "SendSAS"; |
// The prototype of SendSAS(). |
@@ -33,10 +34,10 @@ const wchar_t kSystemPolicyKeyName[] = |
L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"; |
const wchar_t kSoftwareSasValueName[] = L"SoftwareSASGeneration"; |
-const DWORD kEnableSoftwareSasByServices = 1; |
+const DWORD kEnableSoftwareSasByApps = 2; |
// Toggles the default software SAS generation policy to enable SAS generation |
-// by services. Non-default policy is not changed. |
+// by applications. Non-default policy is not changed. |
class ScopedSoftwareSasPolicy { |
public: |
ScopedSoftwareSasPolicy(); |
@@ -88,7 +89,7 @@ bool ScopedSoftwareSasPolicy::Apply() { |
// Override the default policy (i.e. there is no value in the registry) only. |
if (!custom_policy) { |
result = system_policy_.WriteValue(kSoftwareSasValueName, |
- kEnableSoftwareSasByServices); |
+ kEnableSoftwareSasByApps); |
if (result != ERROR_SUCCESS) { |
SetLastError(result); |
LOG_GETLASTERROR(ERROR) |
@@ -121,6 +122,18 @@ class SasInjectorWin : public SasInjector { |
SendSasFunc send_sas_; |
}; |
+// Emulates Secure Attention Sequence (Ctrl+Alt+Del) by switching to |
+// the Winlogon desktop and injecting Ctrl+Alt+Del as a hot key. |
+// N.B. Windows XP/W2K3 only. |
+class SasInjectorXp : public SasInjector { |
+ public: |
+ SasInjectorXp(); |
+ virtual ~SasInjectorXp(); |
+ |
+ // SasInjector implementation. |
+ virtual bool InjectSas() OVERRIDE; |
+}; |
+ |
SasInjectorWin::SasInjectorWin() : send_sas_(NULL) { |
} |
@@ -157,7 +170,7 @@ bool SasInjectorWin::InjectSas() { |
} |
// Enable software SAS generation by services and send SAS. SAS can still fail |
- // if the policy does not allow services to generate software SAS. |
+ // if the policy does not allow applications to generate software SAS. |
ScopedSoftwareSasPolicy enable_sas; |
if (!enable_sas.Apply()) |
return false; |
@@ -166,12 +179,43 @@ bool SasInjectorWin::InjectSas() { |
return true; |
} |
+SasInjectorXp::SasInjectorXp() { |
+} |
+ |
+SasInjectorXp::~SasInjectorXp() { |
+} |
+ |
+bool SasInjectorXp::InjectSas() { |
+ const wchar_t kWinlogonDesktopName[] = L"Winlogon"; |
+ const wchar_t kSasWindowClassName[] = L"SAS window class"; |
+ const wchar_t kSasWindowTitle[] = L"SAS window"; |
+ |
+ scoped_ptr<remoting::Desktop> winlogon_desktop( |
+ remoting::Desktop::GetDesktop(kWinlogonDesktopName)); |
+ if (!winlogon_desktop.get()) |
+ return false; |
+ |
+ remoting::ScopedThreadDesktop desktop; |
+ if (!desktop.SetThreadDesktop(winlogon_desktop.Pass())) |
+ return false; |
+ |
+ HWND window = FindWindow(kSasWindowClassName, kSasWindowTitle); |
+ if (!window) |
+ return false; |
+ |
+ PostMessage(window, |
+ WM_HOTKEY, |
+ 0, |
+ MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); |
+ return true; |
+} |
+ |
scoped_ptr<SasInjector> SasInjector::Create() { |
- if (base::win::GetVersion() >= base::win::VERSION_VISTA) { |
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
+ return scoped_ptr<SasInjector>(new SasInjectorXp()); |
+ } else { |
return scoped_ptr<SasInjector>(new SasInjectorWin()); |
} |
- |
- return scoped_ptr<SasInjector>(); |
} |
} // namespace remoting |