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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel