summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnon Gilboa <agilboa@redhat.com>2009-12-23 15:17:33 +0200
committerYaniv Kamay <ykamay@redhat.com>2009-12-23 15:31:01 +0200
commitf915fa4a72c17e39f750a9154d1a7b4f4eea634e (patch)
treeb8cc2a17096324914a73b23e0c21be56e779d962
parent6b670dfe5cc4bfb92e35ba7a09ec0eff4ec028e5 (diff)
vdagent: add win7 support to service for launching agent0.5.vdiport
-rw-r--r--common/vdlog.cpp3
-rw-r--r--vdagent/vdagent.rc8
-rw-r--r--vdservice/vdservice.cpp150
-rw-r--r--vdservice/vdservice.rc8
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"