[Spice-devel] [PATCH vdagent-win 6/6] vdagent: add vdagent_helper to support mouse when UAC dialog takes focus
Arnon Gilboa
agilboa at redhat.com
Mon Mar 18 06:42:04 PDT 2013
Running the helper with ShellExecute(..."runas"...) is the way to SendInput()
to the UAC dialog in Windows Vista and above.
http://stackoverflow.com/questions/2426594/starting-a-uac-elevated-process-
from-a-non-interactive-service-win32-net-power
http://www.microsoft-questions.com/microsoft/Platform-SDK-Security/29620442/
how-to-proper-use-sendinput-to-a-elevated-window-from-a-service.aspx
rhbz #908422
---
common/vdcommon.h | 1 +
vdagent.sln | 10 +
vdagent/vdagent.cpp | 51 +++++-
vdagent_helper/vdagent_helper.cpp | 46 +++++
vdagent_helper/vdagent_helper.vcproj | 363 ++++++++++++++++++++++++++++++++++
5 files changed, 470 insertions(+), 1 deletions(-)
create mode 100644 vdagent_helper/vdagent_helper.cpp
create mode 100644 vdagent_helper/vdagent_helper.vcproj
diff --git a/common/vdcommon.h b/common/vdcommon.h
index 177721c..5099fdc 100644
--- a/common/vdcommon.h
+++ b/common/vdcommon.h
@@ -34,6 +34,7 @@ typedef CRITICAL_SECTION mutex_t;
#define VD_AGENT_REGISTRY_KEY "SOFTWARE\\Red Hat\\Spice\\vdagent\\"
#define VD_AGENT_STOP_EVENT TEXT("Global\\vdagent_stop_event")
+#define VD_AGENT_NAMED_PIPE TEXT("\\\\.\\pipe\\vdagent")
#if defined __GNUC__
#define ALIGN_GCC __attribute__ ((packed))
diff --git a/vdagent.sln b/vdagent.sln
index 2622f2e..0848ced 100644
--- a/vdagent.sln
+++ b/vdagent.sln
@@ -5,6 +5,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdagent", "vdagent\vdagent.
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdservice", "vdservice\vdservice.vcproj", "{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdagent_helper", "vdagent_helper\vdagent_helper.vcproj", "{3E459EA7-0252-48E0-A92B-13A66F5F370B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -29,6 +31,14 @@ Global
{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.Build.0 = Release|Win32
{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.ActiveCfg = Release|x64
{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|x64.Build.0 = Release|x64
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Debug|Win32.Build.0 = Debug|Win32
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Debug|x64.ActiveCfg = Debug|x64
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Debug|x64.Build.0 = Debug|x64
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Release|Win32.ActiveCfg = Release|Win32
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Release|Win32.Build.0 = Release|Win32
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Release|x64.ActiveCfg = Release|x64
+ {3E459EA7-0252-48E0-A92B-13A66F5F370B}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index f254d55..24fe1f7 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -111,6 +111,7 @@ private:
bool write_message(uint32_t type, uint32_t size, void* data);
bool write_clipboard(VDAgentMessage* msg, uint32_t size);
bool init_vio_serial();
+ bool launch_helper();
bool send_input();
void set_display_depth(uint32_t depth);
void load_display_setting();
@@ -133,6 +134,7 @@ private:
ULONG _mouse_y;
INPUT _input;
DWORD _input_time;
+ HANDLE _helper_pipe;
HANDLE _control_event;
HANDLE _stop_event;
VDAgentMessage* _in_msg;
@@ -189,6 +191,7 @@ VDAgent::VDAgent()
, _mouse_x (0)
, _mouse_y (0)
, _input_time (0)
+ , _helper_pipe (NULL)
, _control_event (NULL)
, _stop_event (NULL)
, _in_msg (NULL)
@@ -287,6 +290,10 @@ bool VDAgent::run()
cleanup();
return false;
}
+ if (!launch_helper()) {
+ cleanup();
+ return false;
+ }
}
_control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!_control_event) {
@@ -342,6 +349,7 @@ bool VDAgent::run()
void VDAgent::cleanup()
{
FreeLibrary(_user_lib);
+ CloseHandle(_helper_pipe);
CloseHandle(_stop_event);
CloseHandle(_control_event);
CloseHandle(_vio_serial);
@@ -393,6 +401,37 @@ void VDAgent::handle_control_event()
MUTEX_UNLOCK(_control_mutex);
}
+bool VDAgent::launch_helper()
+{
+ HINSTANCE helper;
+ TCHAR helper_path[MAX_PATH];
+ TCHAR* slash;
+
+ if (!GetModuleFileName(NULL, helper_path, MAX_PATH) ||
+ !(slash = wcsrchr(helper_path, TCHAR('\\')))) {
+ vd_printf("Cannot get file path: %lu", GetLastError());
+ }
+ wcscpy(slash + 1, L"vdagent_helper.exe");
+ helper = ShellExecute(NULL, L"runas", helper_path, NULL, NULL, SW_HIDE);
+ if (helper <= (HINSTANCE)32) {
+ vd_printf("ShellExecute: %lu", helper);
+ return false;
+ }
+ _helper_pipe = CreateNamedPipe(VD_AGENT_NAMED_PIPE, PIPE_ACCESS_OUTBOUND,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ 1, 1024, 1024, 0, NULL);
+ if (_helper_pipe == INVALID_HANDLE_VALUE) {
+ vd_printf("CreateNamedPipe() failed: %lu", GetLastError());
+ return false;
+ }
+ if (!ConnectNamedPipe(_helper_pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED) {
+ vd_printf("ConnectNamedPipe() failed: %lu", GetLastError());
+ CloseHandle(_helper_pipe);
+ return false;
+ }
+ return true;
+}
+
void VDAgent::input_desktop_message_loop()
{
TCHAR desktop_name[MAX_PATH];
@@ -511,6 +550,8 @@ DWORD VDAgent::get_buttons_change(DWORD last_buttons_state, DWORD new_buttons_st
bool VDAgent::send_input()
{
bool ret = true;
+ DWORD bytes;
+
_desktop_layout->lock();
if (_pending_input) {
if (KillTimer(_hwnd, VD_TIMER_ID)) {
@@ -522,7 +563,14 @@ bool VDAgent::send_input()
return false;
}
}
- if (!SendInput(1, &_input, sizeof(INPUT))) {
+
+ if (_system_version == SYS_VER_WIN_7_CLASS) {
+ if (!WriteFile(_helper_pipe, &_input, sizeof(_input), &bytes, NULL) ||
+ sizeof(_input) != bytes) {
+ vd_printf("Write to pipe failed: %lu", GetLastError());
+ ret = _running = false;
+ }
+ } else if (!SendInput(1, &_input, sizeof(INPUT))) {
DWORD err = GetLastError();
// Don't stop agent due to UIPI blocking, which is usually only for specific windows
// of system security applications (anti-viruses etc.)
@@ -531,6 +579,7 @@ bool VDAgent::send_input()
ret = _running = false;
}
}
+
_input_time = GetTickCount();
_desktop_layout->unlock();
return ret;
diff --git a/vdagent_helper/vdagent_helper.cpp b/vdagent_helper/vdagent_helper.cpp
new file mode 100644
index 0000000..ebeb77b
--- /dev/null
+++ b/vdagent_helper/vdagent_helper.cpp
@@ -0,0 +1,46 @@
+#include <windows.h>
+#include <stdio.h>
+#include <vdlog.h>
+
+int main(int argc,char **argv)
+{
+ TCHAR log_path[MAX_PATH];
+ HANDLE pipe;
+ INPUT input;
+ HDESK hdesk;
+ DWORD bytes;
+ DWORD err = 0;
+ VDLog* log;
+
+ if (GetTempPath(MAX_PATH, log_path)) {
+ wcscat(log_path, L"vdagent_helper.log");
+ log = VDLog::get(log_path);
+ }
+ vd_printf("***vdagent_helper started***");
+ pipe = CreateFile(VD_AGENT_NAMED_PIPE, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+ if (pipe == INVALID_HANDLE_VALUE) {
+ vd_printf("Cannot open pipe %S: %lu", VD_AGENT_NAMED_PIPE, GetLastError());
+ goto fin;
+ }
+ while (ReadFile(pipe, &input, sizeof(input), &bytes, NULL) && bytes == sizeof(input)) {
+ hdesk = OpenInputDesktop(0, FALSE, GENERIC_ALL);
+ if (!hdesk) {
+ vd_printf("OpenInputDesktop() failed: %lu", GetLastError());
+ break;
+ }
+ if (!SetThreadDesktop(hdesk)) {
+ vd_printf("SetThreadDesktop() failed: %lu", GetLastError());
+ CloseDesktop(hdesk);
+ break;
+ }
+ if (!SendInput(1, &input, sizeof(input)) && err != GetLastError()) {
+ err = GetLastError();
+ vd_printf("SendInput() failed: %lu", err);
+ }
+ CloseDesktop(hdesk);
+ }
+ CloseHandle(pipe);
+fin:
+ delete log;
+ return 0;
+}
\ No newline at end of file
diff --git a/vdagent_helper/vdagent_helper.vcproj b/vdagent_helper/vdagent_helper.vcproj
new file mode 100644
index 0000000..47ccb79
--- /dev/null
+++ b/vdagent_helper/vdagent_helper.vcproj
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="vdagent_helper"
+ ProjectGUID="{3E459EA7-0252-48E0-A92B-13A66F5F370B}"
+ RootNamespace="cheese"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\common;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="2"
+ UACUIAccess="false"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\common;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="2"
+ UACUIAccess="false"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\common;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="1"
+ UACUIAccess="false"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\common;$(SPICE_PROTOCOL_DIR)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="Version.lib"
+ LinkIncremental="1"
+ UACUIAccess="false"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\vdagent_helper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\common\vdlog.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\common\vdlog.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--
1.7.7.6
More information about the Spice-devel
mailing list