diff options
author | Arnon Gilboa <agilboa@redhat.com> | 2009-12-23 15:17:33 +0200 |
---|---|---|
committer | Yaniv Kamay <ykamay@redhat.com> | 2009-12-23 15:31:01 +0200 |
commit | f915fa4a72c17e39f750a9154d1a7b4f4eea634e (patch) | |
tree | b8cc2a17096324914a73b23e0c21be56e779d962 | |
parent | 6b670dfe5cc4bfb92e35ba7a09ec0eff4ec028e5 (diff) |
vdagent: add win7 support to service for launching agent0.5.vdiport
-rw-r--r-- | common/vdlog.cpp | 3 | ||||
-rw-r--r-- | vdagent/vdagent.rc | 8 | ||||
-rw-r--r-- | vdservice/vdservice.cpp | 150 | ||||
-rw-r--r-- | vdservice/vdservice.rc | 8 |
4 files changed, 132 insertions, 37 deletions
diff --git a/common/vdlog.cpp b/common/vdlog.cpp index 19f7a7c..1001de3 100644 --- a/common/vdlog.cpp +++ b/common/vdlog.cpp @@ -84,6 +84,7 @@ void log_version() DWORD handle; TCHAR module_fname[MAX_PATH]; TCHAR* info_buf = NULL; + try { if (!GetModuleFileName(NULL, module_fname, MAX_PATH)) { throw; @@ -110,5 +111,5 @@ void log_version() } catch (...) { vd_printf("get version info failed"); } - delete[] info_buf; + delete[] info_buf; } diff --git a/vdagent/vdagent.rc b/vdagent/vdagent.rc index 0d67f82..0973068 100644 --- a/vdagent/vdagent.rc +++ b/vdagent/vdagent.rc @@ -53,8 +53,8 @@ END //
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,5,0,0
- PRODUCTVERSION 0,5,0,0
+ FILEVERSION 0,5,1,0
+ PRODUCTVERSION 0,5,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -71,12 +71,12 @@ BEGIN BEGIN
VALUE "CompanyName", "Red Hat Inc."
VALUE "FileDescription", "Spice agent"
- VALUE "FileVersion", "0, 5, 0, 0"
+ VALUE "FileVersion", "0, 5, 1, 0"
VALUE "InternalName", "vdagent"
VALUE "LegalCopyright", "Copyright (c) 2009 Red Hat Inc. and/or its affiliates"
VALUE "OriginalFilename", "vdagent.exe"
VALUE "ProductName", "Red Hat Spice"
- VALUE "ProductVersion", "0, 5, 0, 0"
+ VALUE "ProductVersion", "0, 5, 1, 0"
END
END
BLOCK "VarFileInfo"
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp index d3b9502..e8a773c 100644 --- a/vdservice/vdservice.cpp +++ b/vdservice/vdservice.cpp @@ -20,6 +20,7 @@ #include <wtsapi32.h> #include <userenv.h> #include <stdio.h> +#include <tlhelp32.h> #include "vdcommon.h" #include "vdi_port.h" #include "mutex.h" @@ -35,6 +36,9 @@ #define VD_AGENT_RESTART_INTERVAL 3000 #define VD_AGENT_RESTART_COUNT_RESET_INTERVAL 60000 #define VD_EVENTS_COUNT 4 +#define WINLOGON_FILENAME TEXT("winlogon.exe") +#define CREATE_PROC_MAX_RETRIES 10 +#define CREATE_PROC_INTERVAL_MS 500 class VDService { public: @@ -78,6 +82,7 @@ private: DWORD _chunk_size; DWORD _last_agent_restart_time; int _agent_restarts; + int _system_version; bool _pipe_connected; bool _pending_reset; bool _pending_write; @@ -97,6 +102,31 @@ VDService* VDService::get() return (VDService*)_singleton; } +enum SystemVersion { + SYS_VER_UNSUPPORTED, + SYS_VER_WIN_XP, + SYS_VER_WIN_7, +}; + +int supported_system_version() +{ + OSVERSIONINFOEX osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (!GetVersionEx((OSVERSIONINFO*)&osvi)) { + vd_printf("GetVersionEx() failed: %u", GetLastError()); + return 0; + } + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { + return SYS_VER_WIN_XP; + } else if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1 && + osvi.wProductType == VER_NT_WORKSTATION) { + return SYS_VER_WIN_7; + } + return 0; +} + VDService::VDService() : _status_handle (0) , _vdi_port (NULL) @@ -117,6 +147,7 @@ VDService::VDService() ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info)); ZeroMemory(&_pipe_state, sizeof(_pipe_state)); ZeroMemory(_events, sizeof(_events)); + _system_version = supported_system_version(); _control_event = CreateEvent(NULL, FALSE, FALSE, NULL); _pipe_state.read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); _agent_path[0] = wchar_t('\0'); @@ -237,7 +268,7 @@ DWORD WINAPI VDService::control_handler(DWORD control, DWORD event_type, LPVOID DWORD session_id = ((WTSSESSION_NOTIFICATION*)event_data)->dwSessionId; vd_printf("Session %u %s", session_id, session_events[event_type]); SetServiceStatus(s->_status_handle, &s->_status); - if (event_type == WTS_CONSOLE_CONNECT) { + if (s->_system_version != SYS_VER_UNSUPPORTED && event_type == WTS_CONSOLE_CONNECT) { s->_session_id = session_id; if (!s->restart_agent(true)) { s->stop(); @@ -412,7 +443,11 @@ bool VDService::execute() break; case WAIT_OBJECT_0 + 3: vd_printf("Agent killed"); - restart_agent(false); + if (_system_version == SYS_VER_WIN_XP) { + restart_agent(false); + } else if (_system_version == SYS_VER_WIN_7) { + kill_agent(); + } break; case WAIT_IO_COMPLETION: case WAIT_TIMEOUT: @@ -600,20 +635,70 @@ BOOL create_session_process_as_user(IN DWORD session_id, IN BOOL use_default_tok return ret; } -bool supported_system_version() +BOOL create_process_as_user(IN DWORD session_id, IN LPCWSTR application_name, + IN LPWSTR command_line, IN LPSECURITY_ATTRIBUTES process_attributes, + IN LPSECURITY_ATTRIBUTES thread_attributes, IN BOOL inherit_handles, + IN DWORD creation_flags, IN LPVOID environment, + IN LPCWSTR current_directory, IN LPSTARTUPINFOW startup_info, + OUT LPPROCESS_INFORMATION process_information) { - OSVERSIONINFOEX osvi; + PROCESSENTRY32 proc_entry; + DWORD winlogon_pid = 0; + HANDLE winlogon_proc; + HANDLE token = NULL; + HANDLE token_dup; + BOOL ret = FALSE; - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx((OSVERSIONINFO*)&osvi)) { - vd_printf("GetVersionEx() failed: %u", GetLastError()); + HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snap == INVALID_HANDLE_VALUE) { + vd_printf("CreateToolhelp32Snapshot() failed %u", GetLastError()); return false; } - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { - return true; + ZeroMemory(&proc_entry, sizeof(proc_entry)); + proc_entry.dwSize = sizeof(PROCESSENTRY32); + if (!Process32First(snap, &proc_entry)) { + vd_printf("Process32First() failed %u", GetLastError()); + CloseHandle(snap); + return false; } - return false; + do { + if (_tcsicmp(proc_entry.szExeFile, WINLOGON_FILENAME) == 0) { + DWORD winlogon_session_id = 0; + if (ProcessIdToSessionId(proc_entry.th32ProcessID, &winlogon_session_id) && + winlogon_session_id == session_id) { + winlogon_pid = proc_entry.th32ProcessID; + break; + } + } + } while (Process32Next(snap, &proc_entry)); + CloseHandle(snap); + if (winlogon_pid == 0) { + vd_printf("Winlogon not found"); + return false; + } + winlogon_proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, winlogon_pid); + if (!winlogon_proc) { + vd_printf("OpenProcess() failed %u", GetLastError()); + return false; + } + ret = OpenProcessToken(winlogon_proc, TOKEN_DUPLICATE, &token); + CloseHandle(winlogon_proc); + if (!ret) { + vd_printf("OpenProcessToken() failed %u", GetLastError()); + return false; + } + ret = DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, + &token_dup); + CloseHandle(token); + if (!ret) { + vd_printf("DuplicateTokenEx() failed %u", GetLastError()); + return false; + } + ret = CreateProcessAsUser(token_dup, application_name, command_line, process_attributes, + thread_attributes, inherit_handles, creation_flags, environment, + current_directory, startup_info, process_information); + CloseHandle(token_dup); + return ret; } bool VDService::launch_agent() @@ -625,24 +710,29 @@ bool VDService::launch_agent() startup_info.cb = sizeof(startup_info); startup_info.lpDesktop = TEXT("Winsta0\\winlogon"); ZeroMemory(&_agent_proc_info, sizeof(_agent_proc_info)); - if (_session_id == 0) { - ret = CreateProcess(_agent_path, _agent_path, NULL, NULL, FALSE, 0, NULL, NULL, - &startup_info, &_agent_proc_info); - } else { - if (!supported_system_version()) { - vd_printf("create_session_process_as_user is not supported by this system version"); - return false; - } - for (int i = 0; i < 20; i++) { - ret = create_session_process_as_user(_session_id, TRUE, NULL, NULL, _agent_path, NULL, - NULL, FALSE, 0, NULL, NULL, &startup_info, - &_agent_proc_info); - if (ret) { - vd_printf("create_session_process_as_user #%d", i); - break; + if (_system_version == SYS_VER_WIN_XP) { + if (_session_id == 0) { + ret = CreateProcess(_agent_path, _agent_path, NULL, NULL, FALSE, 0, NULL, NULL, + &startup_info, &_agent_proc_info); + } else { + for (int i = 0; i < CREATE_PROC_MAX_RETRIES; i++) { + ret = create_session_process_as_user(_session_id, TRUE, NULL, NULL, _agent_path, + NULL, NULL, FALSE, 0, NULL, NULL, + &startup_info, &_agent_proc_info); + if (ret) { + vd_printf("create_session_process_as_user #%d", i); + break; + } + Sleep(CREATE_PROC_INTERVAL_MS); } - Sleep(500); } + } else if (_system_version == SYS_VER_WIN_7) { + startup_info.lpDesktop = TEXT("Winsta0\\default"); + ret = create_process_as_user(_session_id, _agent_path, _agent_path, NULL, NULL, FALSE, 0, + NULL, NULL, &startup_info, &_agent_proc_info); + } else { + vd_printf("Not supported in this system version"); + return false; } if (!ret) { vd_printf("CreateProcess() failed: %u", GetLastError()); @@ -654,7 +744,7 @@ bool VDService::launch_agent() return false; } vd_printf("Wait for vdagent to connect"); - if (ConnectNamedPipe(_pipe_state.pipe, NULL)) { + if (ConnectNamedPipe(_pipe_state.pipe, NULL) || GetLastError() == ERROR_PIPE_CONNECTED) { _pipe_connected = true; _pending_reset = false; vd_printf("Pipe connected by vdagent"); @@ -929,6 +1019,10 @@ void VDService::write_agent_control(uint32_t type, uint32_t opaque) int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { + if (!supported_system_version()) { + printf("vdservice is not supported in this system version\n"); + return 0; + } VDService* vdservice = VDService::get(); if (argc > 1) { if (lstrcmpi(argv[1], TEXT("install")) == 0) { diff --git a/vdservice/vdservice.rc b/vdservice/vdservice.rc index 6215732..f0bf88f 100644 --- a/vdservice/vdservice.rc +++ b/vdservice/vdservice.rc @@ -53,8 +53,8 @@ END //
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,5,0,0
- PRODUCTVERSION 0,5,0,0
+ FILEVERSION 0,5,1,0
+ PRODUCTVERSION 0,5,1,0
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -71,12 +71,12 @@ BEGIN BEGIN
VALUE "CompanyName", "Red Hat Inc."
VALUE "FileDescription", "Spice service"
- VALUE "FileVersion", "0, 5, 0, 0"
+ VALUE "FileVersion", "0, 5, 1, 0"
VALUE "InternalName", "vdservice"
VALUE "LegalCopyright", "Copyright (c) 2009 Red Hat Inc. and/or its affiliates"
VALUE "OriginalFilename", "vdservice.exe"
VALUE "ProductName", "Red Hat Spice"
- VALUE "ProductVersion", "0, 5, 0, 0"
+ VALUE "ProductVersion", "0, 5, 1, 0"
END
END
BLOCK "VarFileInfo"
|