From: Arnon Gilboa <agil...@agilboa.usersys.redhat.com>

---
 common/vdlog.cpp        |    3 +-
 vdagent/vdagent.rc      |    8 +-
 vdservice/vdservice.cpp |  150 ++++++++++++++++++++++++++++++++++++++---------
 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"
-- 
1.5.5.6


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Spice-space-devel mailing list
Spice-space-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spice-space-devel

Reply via email to