[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