[Spice-commits] 13 commits - common/stdint.h common/vdcommon.h vdagent/desktop_layout.h vdagent.sln vdagent/vdagent.cpp vdagent/vdagent.vcproj vdservice/vdi_port.cpp vdservice/vdi_port.h vdservice/vdservice.cpp vdservice/vdservice.vcproj

Alon Levy alon at kemper.freedesktop.org
Mon Aug 23 08:50:50 PDT 2010


 common/stdint.h            |    4 
 common/vdcommon.h          |    9 +
 vdagent.sln                |   14 +
 vdagent/desktop_layout.h   |    2 
 vdagent/vdagent.cpp        |  252 +++++++++++++++++++++++++++++++----
 vdagent/vdagent.vcproj     |  322 ++++++++++++++++++++++++++++++++++++++++++++-
 vdservice/vdi_port.cpp     |  259 ++++++++++++++++++++++++++----------
 vdservice/vdi_port.h       |   30 ++--
 vdservice/vdservice.cpp    |  209 ++++++++++++++++++-----------
 vdservice/vdservice.vcproj |  322 ++++++++++++++++++++++++++++++++++++++++++++-
 10 files changed, 1223 insertions(+), 200 deletions(-)

New commits:
commit 8eb3e2e816714100d82db1f384a2c9c3d5046f10
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Mon Aug 23 16:12:47 2010 +0300

    vdagent: support basic clipboard support (disabled by default)
    
     -add CLIPBOARD_ENABLED ifdefs in the agent for disabling clipboard support
     -currently supports text only (UTF8)

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 20e6205..b7510f2 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -19,6 +19,8 @@
 #include "desktop_layout.h"
 #include <lmcons.h>
 
+//#define CLIPBOARD_ENABLED
+
 #define VD_AGENT_LOG_PATH       TEXT("%svdagent.log")
 #define VD_AGENT_WINCLASS_NAME  TEXT("VDAGENT")
 #define VD_INPUT_INTERVAL_MS    20
@@ -35,7 +37,9 @@ private:
     void input_desktop_message_loop();
     bool handle_mouse_event(VDAgentMouseState* state);
     bool handle_mon_config(VDAgentMonitorsConfig* mon_config, uint32_t port);
+    bool handle_clipboard(VDAgentClipboard* clipboard, uint32_t size);
     bool handle_control(VDPipeMessage* msg);
+    bool on_clipboard_change();
     DWORD get_buttons_change(DWORD last_buttons_state, DWORD new_buttons_state,
                              DWORD mask, DWORD down_flag, DWORD up_flag);
     static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
@@ -45,12 +49,15 @@ private:
     static void dispatch_message(VDAgentMessage* msg, uint32_t port);
     uint8_t* write_lock(DWORD bytes = 0);
     void write_unlock(DWORD bytes = 0);
+    bool write_clipboard();
     bool connect_pipe();
     bool send_input();
 
 private:
     static VDAgent* _singleton;
     HWND _hwnd;
+    HWND _hwnd_next_viewer;
+    bool _clipboard_changer;
     DWORD _buttons_state;
     LONG _mouse_x;
     LONG _mouse_y;
@@ -59,6 +66,9 @@ private:
     HANDLE _desktop_switch_event;
     VDAgentMessage* _in_msg;
     uint32_t _in_msg_pos;
+    VDAgentMessage* _out_msg;
+    uint32_t _out_msg_pos;
+    uint32_t _out_msg_size;
     bool _pending_input;
     bool _pending_write;
     bool _running;
@@ -80,12 +90,17 @@ VDAgent* VDAgent::get()
 
 VDAgent::VDAgent()
     : _hwnd (NULL)
+    , _hwnd_next_viewer (NULL)
+    , _clipboard_changer (false)
     , _buttons_state (0)
     , _mouse_x (0)
     , _mouse_y (0)
     , _input_time (0)
     , _in_msg (NULL)
     , _in_msg_pos (0)
+    , _out_msg (NULL)
+    , _out_msg_pos (0)
+    , _out_msg_size (0)
     , _pending_input (false)
     , _pending_write (false)
     , _running (false)
@@ -224,6 +239,7 @@ void VDAgent::input_desktop_message_loop()
         _running = false;
         return;
     }
+    _hwnd_next_viewer = SetClipboardViewer(_hwnd);
     while (_running && !desktop_switch) {
         wait_ret = MsgWaitForMultipleObjectsEx(1, &_desktop_switch_event, INFINITE, QS_ALLINPUT,
                                                MWMO_ALERTABLE);
@@ -249,6 +265,7 @@ void VDAgent::input_desktop_message_loop()
         KillTimer(_hwnd, VD_TIMER_ID);
         _pending_input = false;
     }
+    ChangeClipboardChain(_hwnd, _hwnd_next_viewer);
     DestroyWindow(_hwnd);
     CloseDesktop(hdesk);
 }
@@ -407,6 +424,48 @@ bool VDAgent::handle_mon_config(VDAgentMonitorsConfig* mon_config, uint32_t port
     return true;
 }
 
+//FIXME: currently supports text only
+bool VDAgent::handle_clipboard(VDAgentClipboard* clipboard, uint32_t size)
+{
+    HGLOBAL clip_data;
+    LPVOID clip_buf;
+    int clip_size;
+    UINT format;
+    bool ret;
+
+    switch (clipboard->type) {
+    case VD_AGENT_CLIPBOARD_UTF8_TEXT:
+        format = CF_UNICODETEXT;
+        break;
+    default:
+        vd_printf("Unsupported clipboard type %u", clipboard->type);
+        return false;
+    }
+    if (!OpenClipboard(_hwnd)) {
+        return false;
+    }
+    clip_size = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)clipboard->data, -1, NULL, 0);
+    if (!clip_size || !(clip_data = GlobalAlloc(GMEM_DDESHARE, clip_size * sizeof(WCHAR)))) {
+        CloseClipboard();
+        return false;
+    }
+    if (!(clip_buf = GlobalLock(clip_data))) {
+        GlobalFree(clip_data);
+        CloseClipboard();
+        return false;
+    }
+    ret = !!MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)clipboard->data, -1, (LPWSTR)clip_buf, clip_size);
+    GlobalUnlock(clip_data);
+    if (ret) {
+        EmptyClipboard();
+        //FIXME: nicify (compare clip_data)
+        _clipboard_changer = true;
+        ret = !!SetClipboardData(format, clip_data);
+    }
+    CloseClipboard();
+    return ret;
+}
+
 bool VDAgent::handle_control(VDPipeMessage* msg)
 {
     switch (msg->type) {
@@ -435,6 +494,78 @@ bool VDAgent::handle_control(VDPipeMessage* msg)
     return true;
 }
 
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+//FIXME: cleanup
+//FIXME: division to max size chunks should NOT be here, but in the service
+//       here we should write the max possible size to the pipe
+bool VDAgent::write_clipboard()
+{
+    ASSERT(_out_msg);
+    DWORD n = MIN(sizeof(VDPipeMessage) + _out_msg_size - _out_msg_pos, VD_AGENT_MAX_DATA_SIZE);
+    VDPipeMessage* pipe_msg = (VDPipeMessage*)write_lock(n);
+    if (!pipe_msg) {
+        return false;
+    }
+    pipe_msg->type = VD_AGENT_COMMAND;
+    //FIXME: client port should be in vd_agent.h
+    pipe_msg->opaque = 1;
+    pipe_msg->size = n - sizeof(VDPipeMessage);
+    memcpy(pipe_msg->data, (char*)_out_msg + _out_msg_pos, n - sizeof(VDPipeMessage));
+    write_unlock(n);
+    if (!_pending_write) {
+        write_completion(0, 0, &_pipe_state.write.overlap);
+    }
+    _out_msg_pos += (n - sizeof(VDPipeMessage));
+    if (_out_msg_pos == _out_msg_size) {
+        delete[] (uint8_t *)_out_msg;
+        _out_msg = NULL;
+        _out_msg_size = 0;
+        _out_msg_pos = 0;
+    }
+    return true;
+}
+
+//FIXME: currently supports text only
+bool VDAgent::on_clipboard_change()
+{
+    UINT format = CF_UNICODETEXT;
+    HANDLE clip_data;
+    LPVOID clip_buf;
+    int clip_size;
+
+    if (_out_msg) {
+        vd_printf("clipboard change is already pending");
+        return false;
+    }
+    if (!IsClipboardFormatAvailable(format) || !OpenClipboard(_hwnd)) {
+        return false;
+    }
+    if (!(clip_data = GetClipboardData(format)) || !(clip_buf = GlobalLock(clip_data))) {
+        CloseClipboard();
+        return false;
+    }
+    clip_size = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, -1, NULL, 0, NULL, NULL);
+    if (!clip_size) {
+        GlobalUnlock(clip_data);
+        CloseClipboard();
+        return false;
+    }
+    _out_msg_pos = 0;
+    _out_msg_size = sizeof(VDAgentMessage) + sizeof(VDAgentClipboard) + clip_size;
+    _out_msg = (VDAgentMessage*)new uint8_t[_out_msg_size];
+    _out_msg->protocol = VD_AGENT_PROTOCOL;
+    _out_msg->type = VD_AGENT_CLIPBOARD;
+    _out_msg->opaque = 0;
+    _out_msg->size = (uint32_t)(sizeof(VDAgentClipboard) + clip_size);
+    VDAgentClipboard* clipboard = (VDAgentClipboard*)_out_msg->data;
+    clipboard->type = VD_AGENT_CLIPBOARD_UTF8_TEXT;
+    WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)clip_buf, -1, (LPSTR)clipboard->data, clip_size, NULL, NULL);
+    GlobalUnlock(clip_data);
+    CloseClipboard();
+    return write_clipboard();
+}
+
 bool VDAgent::connect_pipe()
 {
     VDAgent* a = _singleton;
@@ -479,6 +610,15 @@ void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port)
             a->_running = false;
         }
         break;
+#ifdef CLIPBOARD_ENABLED
+    case VD_AGENT_CLIPBOARD:
+        if (!a->handle_clipboard((VDAgentClipboard*)msg->data,
+                                 msg->size - sizeof(VDAgentClipboard))) {
+            vd_printf("handle_clipboard failed: %u", GetLastError());
+            a->_running = false;
+        }
+        break;
+#endif // CLIPBOARD_ENABLED
     default:
         vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
     }
@@ -577,6 +717,8 @@ VOID CALLBACK VDAgent::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED ove
     ps->write.start += bytes;
     if (ps->write.start == ps->write.end) {
         ps->write.start = ps->write.end = 0;
+        //DEBUG
+        while (a->_out_msg && a->write_clipboard());
     } else if (WriteFileEx(ps->pipe, ps->write.data + ps->write.start,
                            ps->write.end - ps->write.start, overlap, write_completion)) {
         a->_pending_write = true;
@@ -617,6 +759,23 @@ LRESULT CALLBACK VDAgent::wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARA
     case WM_TIMER:
         a->send_input();
         break;
+#ifdef CLIPBOARD_ENABLED
+    case WM_CHANGECBCHAIN:
+        if (a->_hwnd_next_viewer == (HWND)wparam) {
+            a->_hwnd_next_viewer = (HWND)lparam;
+        } else if (a->_hwnd_next_viewer) {
+            SendMessage(a->_hwnd_next_viewer, message, wparam, lparam);
+        }
+        break;
+    case WM_DRAWCLIPBOARD:
+        if (!a->_clipboard_changer) {
+            a->on_clipboard_change();
+        } else {
+            a->_clipboard_changer = false;
+        }
+        SendMessage(a->_hwnd_next_viewer, message, wparam, lparam);
+        break;
+#endif // CLIPBOARD_ENABLED
     default:
         return DefWindowProc(hwnd, message, wparam, lparam);
     }
commit 81cd5620d2e5046cb863d0bc584049b6a760b209
Author: Arnon Gilboa <agilboa at redhat.com>
Date:   Mon Aug 23 16:03:47 2010 +0300

    vdservice/vdagent: fixes leading to clipboard (aka large) message handling
    
    -add VDAgent::dispatch_message()
    -in VDAgent::read_completion() handle multi-chunk msgs
    -fix chunk size bug in VDService::handle_pipe_data()
    -add size to VDPipeMessage

diff --git a/common/vdcommon.h b/common/vdcommon.h
index 8d4b4de..f097de4 100644
--- a/common/vdcommon.h
+++ b/common/vdcommon.h
@@ -44,6 +44,7 @@ enum {
 typedef __declspec (align(1)) struct VDPipeMessage {
     uint32_t type;
     uint32_t opaque;
+    uint32_t size;
     uint8_t data[0];
 } VDPipeMessage;
 
diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index a578dfd..20e6205 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -42,6 +42,7 @@ private:
     static VOID CALLBACK read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlap);
     static VOID CALLBACK write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlap);
     static DWORD WINAPI event_thread_proc(LPVOID param);
+    static void dispatch_message(VDAgentMessage* msg, uint32_t port);
     uint8_t* write_lock(DWORD bytes = 0);
     void write_unlock(DWORD bytes = 0);
     bool connect_pipe();
@@ -56,6 +57,8 @@ private:
     INPUT _input;
     DWORD _input_time;
     HANDLE _desktop_switch_event;
+    VDAgentMessage* _in_msg;
+    uint32_t _in_msg_pos;
     bool _pending_input;
     bool _pending_write;
     bool _running;
@@ -81,6 +84,8 @@ VDAgent::VDAgent()
     , _mouse_x (0)
     , _mouse_y (0)
     , _input_time (0)
+    , _in_msg (NULL)
+    , _in_msg_pos (0)
     , _pending_input (false)
     , _pending_write (false)
     , _running (false)
@@ -386,6 +391,7 @@ bool VDAgent::handle_mon_config(VDAgentMonitorsConfig* mon_config, uint32_t port
     }
     reply_pipe_msg->type = VD_AGENT_COMMAND;
     reply_pipe_msg->opaque = port;
+    reply_pipe_msg->size = sizeof(VDAgentMessage) + sizeof(VDAgentReply);
     reply_msg = (VDAgentMessage*)reply_pipe_msg->data;
     reply_msg->protocol = VD_AGENT_PROTOCOL;
     reply_msg->type = VD_AGENT_REPLY;
@@ -456,6 +462,27 @@ bool VDAgent::connect_pipe()
     vd_printf("Connected to service pipe");
     return true;
 }
+void VDAgent::dispatch_message(VDAgentMessage* msg, uint32_t port)
+{
+    VDAgent* a = _singleton;
+
+    switch (msg->type) {
+    case VD_AGENT_MOUSE_STATE:
+        if (!a->handle_mouse_event((VDAgentMouseState*)msg->data)) {
+            vd_printf("handle_mouse_event failed: %u", GetLastError());
+            a->_running = false;
+        }
+        break;
+    case VD_AGENT_MONITORS_CONFIG:
+        if (!a->handle_mon_config((VDAgentMonitorsConfig*)msg->data, port)) {
+            vd_printf("handle_mon_config failed: %u", GetLastError());
+            a->_running = false;
+        }
+        break;
+    default:
+        vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
+    }
+}
 
 VOID CALLBACK VDAgent::read_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlap)
 {
@@ -480,35 +507,43 @@ VOID CALLBACK VDAgent::read_completion(DWORD err, DWORD bytes, LPOVERLAPPED over
             ps->read.start += sizeof(VDPipeMessage);
             continue;
         }
-        if (len < VD_MESSAGE_HEADER_SIZE) {
+        if (len < sizeof(VDPipeMessage) + pipe_msg->size) {
             break;
         }
-        VDAgentMessage* msg = (VDAgentMessage*)pipe_msg->data;
-        if (len < VD_MESSAGE_HEADER_SIZE + msg->size) {
-            break;
-        }
-        if (msg->protocol != VD_AGENT_PROTOCOL) {
-            vd_printf("Invalid protocol %d", msg->protocol);
-            a->_running = false;
-            break;
-        }
-        switch (msg->type) {
-        case VD_AGENT_MOUSE_STATE:
-            if (!a->handle_mouse_event((VDAgentMouseState*)msg->data)) {
-                vd_printf("handle_mouse_event failed: %d", GetLastError());
-                a->_running = false;
+
+        //FIXME: cleanup, specific to one port
+        if (a->_in_msg_pos == 0 || pipe_msg->opaque == 2 /*FIXME!*/) {
+            if (len < VD_MESSAGE_HEADER_SIZE) {
+                break;
             }
-            break;
-        case VD_AGENT_MONITORS_CONFIG:
-            if (!a->handle_mon_config((VDAgentMonitorsConfig*)msg->data, pipe_msg->opaque)) {
-                vd_printf("handle_mon_config failed: %d", GetLastError());
+            VDAgentMessage* msg = (VDAgentMessage*)pipe_msg->data;
+            if (msg->protocol != VD_AGENT_PROTOCOL) {
+                vd_printf("Invalid protocol %u bytes %u", msg->protocol, bytes);
                 a->_running = false;
+                break;
+            }
+            uint32_t msg_size = sizeof(VDAgentMessage) + msg->size;
+            if (pipe_msg->size == msg_size) {
+                dispatch_message(msg, pipe_msg->opaque);
+            } else {
+                ASSERT(pipe_msg->size < msg_size);
+                a->_in_msg = (VDAgentMessage*)new uint8_t[msg_size];
+                memcpy(a->_in_msg, pipe_msg->data, pipe_msg->size);
+                a->_in_msg_pos = pipe_msg->size;
+            }
+        } else {
+            memcpy((uint8_t*)a->_in_msg + a->_in_msg_pos, pipe_msg->data, pipe_msg->size);
+            a->_in_msg_pos += pipe_msg->size;
+            //vd_printf("DEBUG: pipe_msg size %u pos %u total %u", pipe_msg->size, a->_in_msg_pos, sizeof(VDAgentMessage) + a->_in_msg->size);
+            if (a->_in_msg_pos == sizeof(VDAgentMessage) + a->_in_msg->size) {
+                dispatch_message(a->_in_msg, 0);
+                a->_in_msg_pos = 0;
+                delete[] (uint8_t *)a->_in_msg;
+                a->_in_msg = NULL;
             }
-            break;
-        default:
-            vd_printf("Unsupported message type %d size %d", msg->type, msg->size);
         }
-        ps->read.start += (VD_MESSAGE_HEADER_SIZE + msg->size);
+
+        ps->read.start += (sizeof(VDPipeMessage) + pipe_msg->size);
         if (ps->read.start == ps->read.end) {
             ps->read.start = ps->read.end = 0;
         }
@@ -554,10 +589,11 @@ VOID CALLBACK VDAgent::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED ove
 
 uint8_t* VDAgent::write_lock(DWORD bytes)
 {
+    MUTEX_LOCK(_write_mutex);
     if (_pipe_state.write.end + bytes <= sizeof(_pipe_state.write.data)) {
-        MUTEX_LOCK(_write_mutex);
         return &_pipe_state.write.data[_pipe_state.write.end];
     } else {
+        MUTEX_UNLOCK(_write_mutex);
         vd_printf("write buffer is full");
         return NULL;
     }
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 29b225a..157734b 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -437,8 +437,10 @@ bool VDService::execute()
         if (cont_read >= 0 && cont_write >= 0) {
             cont = cont_read || cont_write;
         } else if (cont_read == VDI_PORT_ERROR || cont_write == VDI_PORT_ERROR) {
+            vd_printf("VDI Port error, read %d write %d", cont_read, cont_write);
             _running = false;
         } else if (cont_read == VDI_PORT_RESET || cont_write == VDI_PORT_RESET) {
+            vd_printf("VDI Port reset, read %d write %d", cont_read, cont_write);
             _chunk_size = _chunk_port = 0;
             write_agent_control(VD_AGENT_RESET, ++_connection_id);
             _pending_reset = true;
@@ -865,6 +867,7 @@ bool VDService::restart_agent(bool normal_restart)
 
 void VDService::stop()
 {
+    vd_printf("Service stopped");
     _running = false;
     if (_control_event && !SetEvent(_control_event)) {
         vd_printf("SetEvent() failed: %u", GetLastError());
@@ -916,9 +919,9 @@ void VDService::read_pipe()
     if (ps->read.end < sizeof(ps->read.data)) {
         _pending_read = true;
         if (ReadFile(ps->pipe, ps->read.data + ps->read.end, sizeof(ps->read.data) - ps->read.end,
-                     &bytes, &ps->read.overlap)) {
+                     &bytes, &ps->read.overlap) || GetLastError() == ERROR_MORE_DATA) {
             _pending_read = false;
-            vd_printf("ReadFile without pending");
+            vd_printf("ReadFile without pending %u", bytes);
             handle_pipe_data(bytes);
             read_pipe();
         } else if (GetLastError() != ERROR_IO_PENDING) {
@@ -932,12 +935,15 @@ void VDService::read_pipe()
     }
 }
 
+//FIXME: division to max size chunks should be here, not in the agent
 void VDService::handle_pipe_data(DWORD bytes)
 {
     VDPipeState* ps = &_pipe_state;
     DWORD read_size;
 
-    _pending_read = false;
+    if (bytes) {
+        _pending_read = false;
+    }
     if (!_running) {
         return;
     }
@@ -949,28 +955,31 @@ void VDService::handle_pipe_data(DWORD bytes)
             ps->read.start += sizeof(VDPipeMessage);
             continue;
         }
-        if (read_size < VD_MESSAGE_HEADER_SIZE) {
+        if (read_size < sizeof(VDPipeMessage) + pipe_msg->size) {
             break;
         }
-        VDAgentMessage* msg = (VDAgentMessage*)pipe_msg->data;
-        DWORD chunk_size = sizeof(VDAgentMessage) + msg->size;
-        VDAgentDataChunk chunk;
-        if (read_size < VD_MESSAGE_HEADER_SIZE + msg->size) {
+        if (_vdi_port->write_ring_free_space() < sizeof(VDAgentDataChunk) + pipe_msg->size) {
+            //vd_printf("DEBUG: no space in write ring %u", _vdi_port->write_ring_free_space());
             break;
         }
         if (!_pending_reset) {
+            VDAgentDataChunk chunk;
             chunk.port = pipe_msg->opaque;
-            chunk.size = chunk_size;
+            chunk.size = pipe_msg->size;
             if (_vdi_port->ring_write(&chunk, sizeof(chunk)) != sizeof(chunk) ||
-                            _vdi_port->ring_write(msg, chunk_size) != chunk_size) {
+                    _vdi_port->ring_write(pipe_msg->data, chunk.size) != chunk.size) {
                 vd_printf("ring_write failed");
                 _running = false;
                 return;
             }
         }
-        ps->read.start += (VD_MESSAGE_HEADER_SIZE + msg->size);
-        if (ps->read.start == ps->read.end) {
-            ps->read.start = ps->read.end = 0;
+        ps->read.start += (sizeof(VDPipeMessage) + pipe_msg->size);
+    }
+    if (ps->read.start == ps->read.end && !_pending_read) {
+        DWORD prev_read_end = ps->read.end;
+        ps->read.start = ps->read.end = 0;
+        if (prev_read_end == sizeof(ps->read.data)) {
+            read_pipe();
         }
     }
 }
@@ -980,7 +989,7 @@ void VDService::handle_port_data()
     VDPipeMessage* pipe_msg;
     VDAgentDataChunk chunk;
     int chunks_count = 0;
-    DWORD count;
+    DWORD count = 0;
 
     while (_running) {
         if (!_chunk_size && _vdi_port->read_ring_size() >= sizeof(chunk)) {
@@ -990,9 +999,6 @@ void VDService::handle_port_data()
                 break;
             }
             count = sizeof(VDPipeMessage) + chunk.size;
-            if (_pipe_state.write.start == _pipe_state.write.end) {
-                _pipe_state.write.start = _pipe_state.write.end = 0;
-            }
             if (_pipe_state.write.end + count > sizeof(_pipe_state.write.data)) {
                 vd_printf("chunk is too large, size %u port %u", chunk.size, chunk.port);
                 _running = false;
@@ -1002,6 +1008,7 @@ void VDService::handle_port_data()
             _chunk_port = chunk.port;
         }
         if (_chunk_size && _vdi_port->read_ring_size() >= _chunk_size) {
+            count = sizeof(VDPipeMessage) + _chunk_size;
             ASSERT(_pipe_state.write.end + count <= sizeof(_pipe_state.write.data));
             pipe_msg = (VDPipeMessage*)&_pipe_state.write.data[_pipe_state.write.end];
             if (_vdi_port->ring_read(pipe_msg->data, _chunk_size) != _chunk_size) {
@@ -1012,6 +1019,7 @@ void VDService::handle_port_data()
             if (_pipe_connected) {
                 pipe_msg->type = VD_AGENT_COMMAND;
                 pipe_msg->opaque = _chunk_port;
+                pipe_msg->size = _chunk_size;
                 _pipe_state.write.end += count;
                 chunks_count++;
             } else {
commit feab0571017629960af5fc46cbaf0582f772e442
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 15:26:05 2010 +0300

    vdservice: change pipe write completion to use overlapped structure instead of completion routine

diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index d30e305..29b225a 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -42,6 +42,7 @@
 
 enum {
     VD_EVENT_PIPE_READ = 0,
+    VD_EVENT_PIPE_WRITE,
     VD_EVENT_CONTROL,
     VD_EVENT_READ,
     VD_EVENT_WRITE,
@@ -64,7 +65,7 @@ private:
     static DWORD WINAPI control_handler(DWORD control, DWORD event_type,
                                         LPVOID event_data, LPVOID context);
     static VOID WINAPI main(DWORD argc, TCHAR * argv[]);
-    static VOID CALLBACK write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlap);
+    void pipe_write_completion();
     void write_agent_control(uint32_t type, uint32_t opaque);
     void read_pipe();
     void handle_pipe_data(DWORD bytes);
@@ -158,6 +159,7 @@ VDService::VDService()
     ZeroMemory(_events, sizeof(_events));
     _system_version = supported_system_version();
     _control_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    _pipe_state.write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
     _pipe_state.read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
     _agent_path[0] = wchar_t('\0');
     MUTEX_INIT(_agent_mutex);
@@ -167,6 +169,7 @@ VDService::VDService()
 VDService::~VDService()
 {
     CloseHandle(_pipe_state.read.overlap.hEvent);
+    CloseHandle(_pipe_state.write.overlap.hEvent);
     CloseHandle(_control_event);
     delete _log;
 }
@@ -419,6 +422,7 @@ bool VDService::execute()
     }
     vd_printf("Connected to server");
     _events[VD_EVENT_PIPE_READ] = _pipe_state.read.overlap.hEvent;
+    _events[VD_EVENT_PIPE_WRITE] = _pipe_state.write.overlap.hEvent;
     _events[VD_EVENT_CONTROL] = _control_event;
     _events[VD_EVENT_READ] = _vdi_port->get_read_event();
     _events[VD_EVENT_WRITE] = _vdi_port->get_write_event();
@@ -442,17 +446,20 @@ bool VDService::execute()
         if (cont) {
             handle_port_data();
         }
+        if (cont_write) {
+            handle_pipe_data(0);
+        }
         if (_running && (!cont || _pending_read || _pending_write)) {
             DWORD events_count = _events[VD_EVENT_AGENT] ? VD_EVENTS_COUNT : VD_EVENTS_COUNT - 1;
-            DWORD wait_ret = WaitForMultipleObjectsEx(events_count, _events, FALSE,
-                                                      cont ? 0 : INFINITE, TRUE);
+            DWORD wait_ret = WaitForMultipleObjects(events_count, _events, FALSE,
+                                                              cont ? 0 : INFINITE);
             switch (wait_ret) {
             case WAIT_OBJECT_0 + VD_EVENT_PIPE_READ: {
                 DWORD bytes = 0;
                 if (_pipe_connected && _pending_read) {
                     _pending_read = false;
-                    if (GetOverlappedResult(_pipe_state.pipe, &_pipe_state.read.overlap, &bytes,
-                                                                                           FALSE)) {
+                    if (GetOverlappedResult(_pipe_state.pipe, &_pipe_state.read.overlap,
+                                            &bytes, FALSE) || GetLastError() == ERROR_MORE_DATA) {
                         handle_pipe_data(bytes);
                         read_pipe();
                     } else {
@@ -463,6 +470,9 @@ bool VDService::execute()
                 }
                 break;
             }
+            case WAIT_OBJECT_0 + VD_EVENT_PIPE_WRITE:
+                pipe_write_completion();
+                break;
             case WAIT_OBJECT_0 + VD_EVENT_CONTROL:
                 vd_printf("Control event");
                 break;
@@ -480,11 +490,10 @@ bool VDService::execute()
                     kill_agent();
                 }
                 break;
-            case WAIT_IO_COMPLETION:
             case WAIT_TIMEOUT:
                 break;
             default:
-                vd_printf("WaitForMultipleObjectsEx failed %u", GetLastError());
+                vd_printf("WaitForMultipleObjects failed %u", GetLastError());
             }
         }
     }
@@ -862,31 +871,40 @@ void VDService::stop()
     }
 }
 
-VOID CALLBACK VDService::write_completion(DWORD err, DWORD bytes, LPOVERLAPPED overlap)
+void VDService::pipe_write_completion()
 {
-    VDService* s = _singleton;
-    VDPipeState* ps = &s->_pipe_state;
+    VDPipeState* ps = &this->_pipe_state;
+    DWORD bytes;
 
-    s->_pending_write = false;
-    if (!s->_running) {
-        return;
-    }
-    if (err) {
-        vd_printf("error %u", err);
+    if (!_running) {
         return;
     }
-    ps->write.start += bytes;
+    if (_pending_write) {
+        if (GetOverlappedResult(_pipe_state.pipe, &_pipe_state.write.overlap, &bytes, FALSE)) {
+            ps->write.start += bytes;
+            if (ps->write.start == ps->write.end) {
+                ps->write.start = ps->write.end = 0;
+            }
+        } else if (GetLastError() == ERROR_IO_PENDING){
+            vd_printf("Overlapped write is pending");
+            return;
+        } else {
+            vd_printf("GetOverlappedResult() failed : %d", GetLastError());
+        }
+	    _pending_write = false;
+	}
+
     if (ps->write.start < ps->write.end) {
-        s->_pending_write = true;
-        if (!WriteFileEx(ps->pipe, ps->write.data + ps->write.start,
-                         ps->write.end - ps->write.start, overlap, write_completion)) {
-            vd_printf("WriteFileEx() failed: %u", GetLastError());
-            s->_pending_write = false;
-            s->_pipe_connected = false;
-            DisconnectNamedPipe(s->_pipe_state.pipe);
+        _pending_write = true;
+        if (!WriteFile(ps->pipe, ps->write.data + ps->write.start,
+                       ps->write.end - ps->write.start, NULL, &_pipe_state.write.overlap)) {
+            vd_printf("WriteFile() failed: %u", GetLastError());
+            _pending_write = false;
+            _pipe_connected = false;
+            DisconnectNamedPipe(_pipe_state.pipe);
         }
     } else {
-        s->_pending_write = false;
+        _pending_write = false;
     }
 }
 
@@ -1006,7 +1024,7 @@ void VDService::handle_port_data()
         }
     }
     if (_pipe_connected && chunks_count && !_pending_write) {
-        write_completion(0, 0, &_pipe_state.write.overlap);
+        pipe_write_completion();
     }
 }
 
@@ -1044,7 +1062,7 @@ void VDService::write_agent_control(uint32_t type, uint32_t opaque)
     msg->opaque = opaque;
     _pipe_state.write.end += sizeof(VDPipeMessage);
     if (!_pending_write) {
-        write_completion(0, 0, &_pipe_state.write.overlap);
+        pipe_write_completion();
     }
 }
 
commit f3277bd9b7760476966615f3a496db32dd37f717
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 15:09:28 2010 +0300

    vdservice: add debug only define for standalone executable

diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index c608317..d30e305 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -24,6 +24,8 @@
 #include "vdcommon.h"
 #include "vdi_port.h"
 
+//#define DEBUG_VDSERVICE
+
 #define VD_SERVICE_DISPLAY_NAME TEXT("RHEV Spice Agent")
 #define VD_SERVICE_NAME         TEXT("vdservice")
 #define VD_SERVICE_DESCRIPTION  TEXT("Enables Spice event injection and display configuration.")
@@ -171,8 +173,13 @@ VDService::~VDService()
 
 bool VDService::run()
 {
+#ifndef DEBUG_VDSERVICE
     SERVICE_TABLE_ENTRY service_table[] = {{VD_SERVICE_NAME, main}, {0, 0}};
     return !!StartServiceCtrlDispatcher(service_table);
+#else
+    main(0, NULL);
+    return true;
+#endif
 }
 
 bool VDService::install()
@@ -336,7 +343,9 @@ VOID WINAPI VDService::main(DWORD argc, TCHAR* argv[])
                                                      NULL);
     if (!s->_status_handle) {
         printf("RegisterServiceCtrlHandler failed\n");
+#ifndef DEBUG_VDSERVICE
         return;
+#endif // DEBUG_VDSERVICE
     }
 
     // service is starting
@@ -358,7 +367,9 @@ VOID WINAPI VDService::main(DWORD argc, TCHAR* argv[])
     // service is stopped
     status->dwControlsAccepted &= ~VDSERVICE_ACCEPTED_CONTROLS;
     status->dwCurrentState = SERVICE_STOPPED;
+#ifndef DEBUG_VDSERVICE
     SetServiceStatus(s->_status_handle, status);
+#endif //DEBUG_VDSERVICE
 }
 
 typedef __declspec (align(1)) struct VDAgentDataChunk {
commit a32359a4dd7c9bdd0642fa3fc9f61a79218f3395
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 15:06:31 2010 +0300

    vdservice: use enum for events in main loop

diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 61f6a54..c608317 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -34,11 +34,19 @@
 #define VD_AGENT_MAX_RESTARTS   10
 #define VD_AGENT_RESTART_INTERVAL 3000
 #define VD_AGENT_RESTART_COUNT_RESET_INTERVAL 60000
-#define VD_EVENTS_COUNT         5
 #define WINLOGON_FILENAME       TEXT("winlogon.exe")
 #define CREATE_PROC_MAX_RETRIES 10
 #define CREATE_PROC_INTERVAL_MS 500
 
+enum {
+    VD_EVENT_PIPE_READ = 0,
+    VD_EVENT_CONTROL,
+    VD_EVENT_READ,
+    VD_EVENT_WRITE,
+    VD_EVENT_AGENT, // Must be before last
+    VD_EVENTS_COUNT // Must be last
+};
+
 class VDService {
 public:
     static VDService* get();
@@ -399,11 +407,11 @@ bool VDService::execute()
         return false;
     }
     vd_printf("Connected to server");
-    _events[0] = _pipe_state.read.overlap.hEvent;
-    _events[1] = _control_event;
-    _events[2] = _vdi_port->get_read_event();
-    _events[3] = _vdi_port->get_write_event();
-    _events[4] = _agent_proc_info.hProcess;
+    _events[VD_EVENT_PIPE_READ] = _pipe_state.read.overlap.hEvent;
+    _events[VD_EVENT_CONTROL] = _control_event;
+    _events[VD_EVENT_READ] = _vdi_port->get_read_event();
+    _events[VD_EVENT_WRITE] = _vdi_port->get_write_event();
+    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
     _chunk_size = _chunk_port = 0;
     read_pipe();
     while (_running) {
@@ -424,12 +432,11 @@ bool VDService::execute()
             handle_port_data();
         }
         if (_running && (!cont || _pending_read || _pending_write)) {
-            DWORD events_count = _events[VD_EVENTS_COUNT - 1] ? VD_EVENTS_COUNT :
-                                                                VD_EVENTS_COUNT - 1;
+            DWORD events_count = _events[VD_EVENT_AGENT] ? VD_EVENTS_COUNT : VD_EVENTS_COUNT - 1;
             DWORD wait_ret = WaitForMultipleObjectsEx(events_count, _events, FALSE,
                                                       cont ? 0 : INFINITE, TRUE);
             switch (wait_ret) {
-            case WAIT_OBJECT_0 + 0: {
+            case WAIT_OBJECT_0 + VD_EVENT_PIPE_READ: {
                 DWORD bytes = 0;
                 if (_pipe_connected && _pending_read) {
                     _pending_read = false;
@@ -445,16 +452,16 @@ bool VDService::execute()
                 }
                 break;
             }
-            case WAIT_OBJECT_0 + 1:
+            case WAIT_OBJECT_0 + VD_EVENT_CONTROL:
                 vd_printf("Control event");
                 break;
-            case WAIT_OBJECT_0 + 2:
+            case WAIT_OBJECT_0 + VD_EVENT_READ:
                 _vdi_port->read_completion();
                 break;
-            case WAIT_OBJECT_0 + 3:
+            case WAIT_OBJECT_0 + VD_EVENT_WRITE:
                 _vdi_port->write_completion();
                 break;
-            case WAIT_OBJECT_0 + 4:
+            case WAIT_OBJECT_0 + VD_EVENT_AGENT:
                 vd_printf("Agent killed");
                 if (_system_version == SYS_VER_WIN_XP) {
                     restart_agent(false);
@@ -765,7 +772,7 @@ bool VDService::launch_agent()
         vd_printf("ConnectNamedPipe() failed: %u", GetLastError());
         return false;
     }
-    _events[VD_EVENTS_COUNT - 1] = _agent_proc_info.hProcess;
+    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
     return true;
 }
 
@@ -778,7 +785,7 @@ bool VDService::kill_agent()
     if (!_agent_alive) {
         return true;
     }
-    _events[VD_EVENTS_COUNT - 1] = 0;
+    _events[VD_EVENT_AGENT] = 0;
     _agent_alive = false;
     if (_pipe_connected) {
         _pipe_connected = false;
commit a6c1ab59cac9f02b6f3263e07d3db82bdc6e7536
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 14:57:02 2010 +0300

    vdservice: remove dead defines in vdi_port.h

diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index 08cfee1..a10b346 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -23,10 +23,6 @@
 
 #define BUF_SIZE    (1024 * 1024)
 
-#define BUF_READ    (1 << 0)
-#define BUF_WRITE   (1 << 1)
-#define BUF_ALL     (BUF_READ | BUF_WRITE)
-
 #define VDI_PORT_BLOCKED    0
 #define VDI_PORT_RESET      -1
 #define VDI_PORT_ERROR      -2
commit 1724de8a4312fcdb59f57e2e8738c624ce902a66
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 14:50:41 2010 +0300

    vdservice: replace vdiport device with virtio-serial device
    
    replaced vdiport device by virtio-serial device which is also an easy
    to use stream between guest and host but is already in qemu.
    
     * VDIPortBuffer split off from VDIPort
     * use setupapi to get device path
      * setupapi.lib dependency added, magic GUID instead of a magic filename
     * retry several times to open device, fixes startup race between driver
       initialization and service start on boot.
     * limit writes to device, a limitation of current windows driver.
     * virtio-serial uses overlapped structure and events for async read/write
       instead of vdi_port special event.

diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
index 4c0a99d..0d5c0e1 100644
--- a/vdservice/vdi_port.cpp
+++ b/vdservice/vdi_port.cpp
@@ -15,35 +15,35 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <windows.h>
+#include <setupapi.h>
 #include "stdio.h"
 #include "vdi_port.h"
 #include "vdlog.h"
 
-#define VDI_PORT_DEV_NAME   TEXT("\\\\.\\VDIPort")
-#define FILE_DEVICE_UNKNOWN 0x00000022
-#define METHOD_BUFFERED     0
-#define FILE_ANY_ACCESS     0
+const GUID GUID_VIOSERIAL_PORT =
+    {0x6fde7521, 0x1b65, 0x48ae, 0xb6, 0x28, 0x80, 0xbe, 0x62, 0x1, 0x60, 0x26};
 
-#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
+// Current limitation of virtio-serial windows driver (RHBZ 617000)
+#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
 
-#define FIRST_AVAIL_IO_FUNC 0x800
-#define RED_TUNNEL_CTL_FUNC FIRST_AVAIL_IO_FUNC
-
-#define IOCTL_RED_TUNNEL_SET_EVENT \
-    CTL_CODE(FILE_DEVICE_UNKNOWN, RED_TUNNEL_CTL_FUNC, METHOD_BUFFERED, FILE_ANY_ACCESS)
+// Retry initial connection to device. On boot when vdservice is started the device is
+// not immediately available (takes 2 seconds, 30 is for extreme load).
+#define VIOSERIAL_PORT_DEVICE_OPEN_MAX_RETRIES          30
+#define VIOSERIAL_PORT_DEVICE_OPEN_RETRY_INTERVAL_MS    1000
 
 #define MIN(a, b) ((a) > (b) ? (b) : (a))
 
+VDIPort* VDIPort::_singleton;
+
 VDIPort::VDIPort()
     : _handle (INVALID_HANDLE_VALUE)
-    , _event (NULL)
-    , _write_start (_write_ring)
-    , _write_end (_write_ring)
-    , _read_start (_read_ring)
-    , _read_end (_read_ring)
 {
+    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
+    _write.start = _write.end = _write.ring;
+    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
+    _read.start = _read.end = _read.ring;
+    _singleton = this;
 }
 
 VDIPort::~VDIPort()
@@ -51,77 +51,172 @@ VDIPort::~VDIPort()
     if (_handle != INVALID_HANDLE_VALUE) {
         CloseHandle(_handle);
     }
-    if (_event) {
-        CloseHandle(_event);
+    if (_read.overlap.hEvent) {
+        CloseHandle(_read.overlap.hEvent);
+    }
+    if (_write.overlap.hEvent) {
+        CloseHandle(_write.overlap.hEvent);
+    }
+}
+
+//Based on device.cpp from vioserial test app
+//FIXME: remove this call & lib?
+PTCHAR get_device_path(IN LPGUID interface_guid)
+{
+    HDEVINFO dev_info;
+    SP_DEVICE_INTERFACE_DATA dev_interface;
+    PSP_DEVICE_INTERFACE_DETAIL_DATA dev_interface_detail = NULL;
+    ULONG len, req_len = 0;
+
+    dev_info = SetupDiGetClassDevs(interface_guid, NULL, NULL,
+                                   DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+    if (dev_info == INVALID_HANDLE_VALUE) {
+        vd_printf("Cannot get class devices");
+        return NULL;
+    }
+    dev_interface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+    if (!SetupDiEnumDeviceInterfaces(dev_info, 0, interface_guid, 0, &dev_interface)) {
+        vd_printf("Cannot get enumerate device interfaces");
+        SetupDiDestroyDeviceInfoList(dev_info);
+        return NULL;
     }
+    SetupDiGetDeviceInterfaceDetail(dev_info, &dev_interface, NULL, 0, &req_len, NULL);
+    dev_interface_detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, req_len);
+    if (dev_interface_detail == NULL) {
+        vd_printf("Cannot allocate memory");
+        SetupDiDestroyDeviceInfoList(dev_info);
+        return NULL;
+    }
+    dev_interface_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+    len = req_len;
+    if (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_interface, dev_interface_detail, len,
+                                         &req_len, NULL)) {
+        vd_printf("Cannot get device interface details.\n");
+        SetupDiDestroyDeviceInfoList(dev_info);
+        LocalFree(dev_interface_detail);
+        return NULL;
+    }
+    return dev_interface_detail->DevicePath;
 }
 
 bool VDIPort::init()
 {
-    DWORD io_ret_len;
-    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                         OPEN_EXISTING, 0, NULL);
+    PTCHAR path = NULL;
+
+    for (int retry = 0; retry < VIOSERIAL_PORT_DEVICE_OPEN_MAX_RETRIES && path == NULL; retry++) {
+        if (path = get_device_path((LPGUID)&GUID_VIOSERIAL_PORT)) {
+            break;
+        }
+        Sleep(VIOSERIAL_PORT_DEVICE_OPEN_RETRY_INTERVAL_MS);
+    }
+    if (path == NULL) {
+        vd_printf("GetDevicePath failed - device/driver missing?");
+        return false;
+    }
+    _handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     if (_handle == INVALID_HANDLE_VALUE) {
         vd_printf("CreateFile() failed: %u", GetLastError());
         return false;
     }
-    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_event == NULL) {
+    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_write.overlap.hEvent == NULL) {
         vd_printf("CreateEvent() failed: %u", GetLastError());
         return false;
     }
-    if (!DeviceIoControl(_handle, IOCTL_RED_TUNNEL_SET_EVENT, &_event, sizeof(_event),
-                         NULL, 0, &io_ret_len, NULL)) {
-        vd_printf("DeviceIoControl() failed: %u", GetLastError());
+    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_read.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %u", GetLastError());
         return false;
     }
     return true;
 }
 
+size_t VDIPort::write_ring_free_space()
+{
+    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
+}
+
 size_t VDIPort::ring_write(const void* buf, size_t size)
 {
-    size_t free_size = (BUF_SIZE + _write_start - _write_end - 1) % BUF_SIZE;
+    size_t free_size = (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
     size_t n;
 
     if (size > free_size) {
         size = free_size;
     }
-    if (_write_end < _write_start) {
-        memcpy(_write_end, buf, size);
+    if (_write.end < _write.start) {
+        memcpy(_write.end, buf, size);
     } else {
-        n = MIN(size, (size_t)(&_write_ring[BUF_SIZE] - _write_end));
-        memcpy(_write_end, buf, n);
+        n = MIN(size, (size_t)(&_write.ring[BUF_SIZE] - _write.end));
+        memcpy(_write.end, buf, n);
         if (size > n) {
-            memcpy(_write_ring, (uint8_t*)buf + n, size - n);
+            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
         }
     }
-    _write_end = _write_ring + (_write_end - _write_ring + size) % BUF_SIZE;
+    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
     return size;
 }
 
 int VDIPort::write()
 {
     int size;
-    int n;
+    int ret;
 
-    if (_write_start == _write_end) {
+    //FIXME: return VDI_PORT_NO_DATA
+    if (_write.start == _write.end) {
         return 0;
     }
-    if (_write_start < _write_end) {
-        size = (int)(_write_end - _write_start);
-    } else {
-        size = (int)(&_write_ring[BUF_SIZE] - _write_start);
+    if (!_write.pending) {
+        if (_write.start < _write.end) {
+            size = (int)(_write.end - _write.start);
+        } else {
+            size = (int)(&_write.ring[BUF_SIZE] - _write.start);
+        }
+        size = MIN(size, VIOSERIAL_PORT_MAX_WRITE_BYTES);
+        _write.pending = true;
+        if (WriteFile(_handle, _write.start, size, NULL, &_write.overlap)) {
+            write_completion();
+        } if (GetLastError() != ERROR_IO_PENDING) {
+            return handle_error();
+        }
     }
-    if (!WriteFile(_handle, _write_start, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
+    ret = _write.bytes;
+    _write.bytes = 0;
+    return ret;
+}
+
+void VDIPort::write_completion()
+{
+    DWORD bytes;
+
+    if (!_write.pending) {
+        return;
     }
-    _write_start = _write_ring + (_write_start - _write_ring + n) % BUF_SIZE;
-    return n;
+    if (!GetOverlappedResult(_handle, &_write.overlap, &bytes, FALSE)) {
+        vd_printf("GetOverlappedResult failed: %u", GetLastError());
+        return;
+    }
+    _write.start = _write.ring + (_write.start - _write.ring + bytes) % BUF_SIZE;
+    _write.bytes = bytes;
+    _write.pending = false;
 }
 
 size_t VDIPort::read_ring_size()
 {
-    return (BUF_SIZE + _read_end - _read_start) % BUF_SIZE;
+    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
+}
+
+size_t VDIPort::read_ring_continuous_remaining_size()
+{
+    DWORD size;
+
+    if (_read.start <= _read.end) {
+        size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+    } else {
+        size = (DWORD)(_read.start - _read.end - 1);
+    }
+    return size;
 }
 
 size_t VDIPort::ring_read(void* buf, size_t size)
@@ -129,45 +224,67 @@ size_t VDIPort::ring_read(void* buf, size_t size)
     size_t n;
     size_t m = 0;
 
-    if (_read_start == _read_end) {
+    if (_read.start == _read.end) {
         return 0;
     }
-    if (_read_start < _read_end) {
-        n = MIN(size, (size_t)(_read_end - _read_start));
-        memcpy(buf, _read_start, n);
+    if (_read.start < _read.end) {
+        n = MIN(size, (size_t)(_read.end - _read.start));
+        memcpy(buf, _read.start, n);
     } else {
-        n = MIN(size, (size_t)(&_read_ring[BUF_SIZE] - _read_start));
-        memcpy(buf, _read_start, n);
+        n = MIN(size, (size_t)(&_read.ring[BUF_SIZE] - _read.start));
+        memcpy(buf, _read.start, n);
         if (size > n) {
-            m = MIN(size - n, (size_t)(_read_end - _read_ring));
-            memcpy((uint8_t*)buf + n, _read_ring, m);
+            m = MIN(size - n, (size_t)(_read.end - _read.ring));
+            memcpy((uint8_t*)buf + n, _read.ring, m);
         }
     }
-    _read_start = _read_ring + (_read_start - _read_ring + n + m) % BUF_SIZE;
+    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
     return n + m;
 }
 
 int VDIPort::read()
 {
     int size;
-    int n;
+    int ret;
 
-    if ((_read_end - _read_ring + 1) % BUF_SIZE == _read_start - _read_ring) {
-        return 0;
-    }
-    if (_read_start == _read_end) {
-        _read_start = _read_end = _read_ring;
-    }
-    if (_read_start <= _read_end) {
-        size = MIN(BUF_SIZE - 1, (int)(&_read_ring[BUF_SIZE] - _read_end));
-    } else {
-        size = (int)(_read_start - _read_end - 1);
+    if (!_read.pending) {
+        //FIXME: read_ring_continuous_remaining_size? return VDI_PORT_BUFFER_FULL
+        if ((_read.end - _read.ring + 1) % BUF_SIZE == _read.start - _read.ring) {
+            vd_printf("DEBUG: buffer full");
+            return 0;
+        }
+        if (_read.start == _read.end) {
+            _read.start = _read.end = _read.ring;
+        }
+        if (_read.start <= _read.end) {
+            size = MIN(BUF_SIZE - 1, (int)(&_read.ring[BUF_SIZE] - _read.end));
+        } else {
+            size = (int)(_read.start - _read.end - 1);
+        }
+        _read.pending = true;
+        if (ReadFile(_handle, _read.end, size, NULL, &_read.overlap)) {
+            read_completion();
+        } else if (GetLastError() != ERROR_IO_PENDING) {
+            return handle_error();
+        }
     }
-    if (!ReadFile(_handle, _read_end, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
+    ret = _read.bytes;
+    _read.bytes = 0;
+    return ret;
+}
+
+void VDIPort::read_completion()
+{
+    DWORD bytes;
+
+    if (!GetOverlappedResult(_handle, &_read.overlap, &bytes, FALSE) &&
+                                      GetLastError() != ERROR_MORE_DATA) {
+        vd_printf("GetOverlappedResult failed: %u", GetLastError());
+        return;
     }
-    _read_end = _read_ring + (_read_end - _read_ring + n) % BUF_SIZE;
-    return n;
+    _read.end = _read.ring + (_read.end - _read.ring + bytes) % BUF_SIZE;
+    _read.bytes = bytes;
+    _read.pending = false;
 }
 
 int VDIPort::handle_error()
@@ -175,8 +292,8 @@ int VDIPort::handle_error()
     switch (GetLastError()) {
     case ERROR_CONNECTION_INVALID:
         vd_printf("port reset");
-        _write_start = _write_end = _write_ring;
-        _read_start = _read_end = _read_ring;
+        _write.start = _write.end = _write.ring;
+        _read.start = _read.end = _read.ring;
         return VDI_PORT_RESET;
     default:
         vd_printf("port io failed: %u", GetLastError());
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index 3af3f18..08cfee1 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -31,30 +31,40 @@
 #define VDI_PORT_RESET      -1
 #define VDI_PORT_ERROR      -2
 
+typedef struct VDIPortBuffer {
+    OVERLAPPED overlap;
+    uint8_t* start;
+    uint8_t* end;
+    bool pending;
+    int bytes;
+    uint8_t ring[BUF_SIZE];
+} VDIPortBuffer;
+
 class VDIPort {
 public:
     VDIPort();
     ~VDIPort();
     bool init();
     size_t ring_write(const void* buf, size_t size);
+    size_t write_ring_free_space();
     size_t ring_read(void* buf, size_t size);
     size_t read_ring_size();
+    size_t read_ring_continuous_remaining_size();
+    HANDLE get_write_event() { return _write.overlap.hEvent; }
+    HANDLE get_read_event() { return _read.overlap.hEvent; }
     int write();
     int read();
-    HANDLE get_event() { return _event;}
+    void write_completion();
+    void read_completion();
 
 private:
     int handle_error();
 
 private:
+    static VDIPort* _singleton;
     HANDLE _handle;
-    HANDLE _event;
-    uint8_t _write_ring[BUF_SIZE];
-    uint8_t* _write_start;
-    uint8_t* _write_end;
-    uint8_t _read_ring[BUF_SIZE];
-    uint8_t* _read_start;
-    uint8_t* _read_end;
+    VDIPortBuffer _write;
+    VDIPortBuffer _read;
 };
 
 // Ring notes:
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 903fff6..61f6a54 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -34,7 +34,7 @@
 #define VD_AGENT_MAX_RESTARTS   10
 #define VD_AGENT_RESTART_INTERVAL 3000
 #define VD_AGENT_RESTART_COUNT_RESET_INTERVAL 60000
-#define VD_EVENTS_COUNT         4
+#define VD_EVENTS_COUNT         5
 #define WINLOGON_FILENAME       TEXT("winlogon.exe")
 #define CREATE_PROC_MAX_RETRIES 10
 #define CREATE_PROC_INTERVAL_MS 500
@@ -399,10 +399,11 @@ bool VDService::execute()
         return false;
     }
     vd_printf("Connected to server");
-    _events[0] = _vdi_port->get_event();
-    _events[1] = _pipe_state.read.overlap.hEvent;
-    _events[2] = _control_event;
-    _events[3] = _agent_proc_info.hProcess;
+    _events[0] = _pipe_state.read.overlap.hEvent;
+    _events[1] = _control_event;
+    _events[2] = _vdi_port->get_read_event();
+    _events[3] = _vdi_port->get_write_event();
+    _events[4] = _agent_proc_info.hProcess;
     _chunk_size = _chunk_port = 0;
     read_pipe();
     while (_running) {
@@ -428,9 +429,7 @@ bool VDService::execute()
             DWORD wait_ret = WaitForMultipleObjectsEx(events_count, _events, FALSE,
                                                       cont ? 0 : INFINITE, TRUE);
             switch (wait_ret) {
-            case WAIT_OBJECT_0:
-                break;
-            case WAIT_OBJECT_0 + 1: {
+            case WAIT_OBJECT_0 + 0: {
                 DWORD bytes = 0;
                 if (_pipe_connected && _pending_read) {
                     _pending_read = false;
@@ -446,10 +445,16 @@ bool VDService::execute()
                 }
                 break;
             }
-            case WAIT_OBJECT_0 + 2:
+            case WAIT_OBJECT_0 + 1:
                 vd_printf("Control event");
                 break;
+            case WAIT_OBJECT_0 + 2:
+                _vdi_port->read_completion();
+                break;
             case WAIT_OBJECT_0 + 3:
+                _vdi_port->write_completion();
+                break;
+            case WAIT_OBJECT_0 + 4:
                 vd_printf("Agent killed");
                 if (_system_version == SYS_VER_WIN_XP) {
                     restart_agent(false);
diff --git a/vdservice/vdservice.vcproj b/vdservice/vdservice.vcproj
index 4e70a8b..85d5c8e 100644
--- a/vdservice/vdservice.vcproj
+++ b/vdservice/vdservice.vcproj
@@ -65,7 +65,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib setupapi.lib"
 				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
@@ -216,7 +216,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib setupapi.lib"
 				LinkIncremental="1"
 				GenerateDebugInformation="true"
 				SubSystem="1"
commit a17ccbf323768c3cb977f0f062366ba7cf7f19db
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Aug 23 14:46:01 2010 +0300

    include path fixes because of spice-protcol updates
    
     * mutex.h inlined into common/vdcommon.h
     * vdagent.h renamed to spice/vd_agent.h

diff --git a/common/vdcommon.h b/common/vdcommon.h
index 2e4ed5d..8d4b4de 100644
--- a/common/vdcommon.h
+++ b/common/vdcommon.h
@@ -21,9 +21,15 @@
 #pragma warning(disable:4200)
 
 #include <windows.h>
-#include "vd_agent.h"
+#include "spice/vd_agent.h"
 #include "vdlog.h"
 
+typedef CRITICAL_SECTION mutex_t;
+
+#define MUTEX_INIT(mutex) InitializeCriticalSection(&mutex)
+#define MUTEX_LOCK(mutex) EnterCriticalSection(&mutex)
+#define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex)
+
 #define VD_SERVICE_PIPE_NAME   TEXT("\\\\.\\pipe\\vdservicepipe")
 #define VD_MESSAGE_HEADER_SIZE (sizeof(VDPipeMessage) + sizeof(VDAgentMessage))
 #define VD_PIPE_BUF_SIZE       (1024 * 1024)
diff --git a/vdagent/desktop_layout.h b/vdagent/desktop_layout.h
index 797a82c..dc8accb 100644
--- a/vdagent/desktop_layout.h
+++ b/vdagent/desktop_layout.h
@@ -18,8 +18,8 @@
 #ifndef _H_DESKTOP_LAYOUT
 #define _H_DESKTOP_LAYOUT
 
-#include "mutex.h"
 #include <vector>
+#include "vdcommon.h"
 
 class DisplayMode {
 public:
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 8139af4..903fff6 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -23,7 +23,6 @@
 #include <tlhelp32.h>
 #include "vdcommon.h"
 #include "vdi_port.h"
-#include "mutex.h"
 
 #define VD_SERVICE_DISPLAY_NAME TEXT("RHEV Spice Agent")
 #define VD_SERVICE_NAME         TEXT("vdservice")
commit c909771c0e6f7a529d0ec614d57dcd500b500990
Author: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
Date:   Sun Jun 6 12:51:04 2010 +0300

    spice: vdagent: drop mouse event when SendInput fails due to DesktopSwitch event delay #598968

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 332438b..a578dfd 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -262,7 +262,7 @@ DWORD VDAgent::get_buttons_change(DWORD last_buttons_state, DWORD new_buttons_st
 
 bool VDAgent::send_input()
 {
-    UINT ret;
+    bool ret = true;
     _desktop_layout->lock();
     if (_pending_input) {
         if (KillTimer(_hwnd, VD_TIMER_ID)) {
@@ -274,14 +274,13 @@ bool VDAgent::send_input()
             return false;
         }
     }
-    ret = SendInput(1, &_input, sizeof(INPUT));
-    if (!ret) {
+    if (!SendInput(1, &_input, sizeof(INPUT)) && GetLastError() != ERROR_ACCESS_DENIED) {
         vd_printf("SendInput failed: %d", GetLastError());
-        _running = false;
+        ret = _running = false;
     }
     _input_time = GetTickCount();
     _desktop_layout->unlock();
-    return !!ret;
+    return ret;
 }
 
 bool VDAgent::handle_mouse_event(VDAgentMouseState* state)
commit b850d5a8c79b96dbe884276cef9feee0c3e8c424
Author: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
Date:   Mon Mar 22 17:17:18 2010 +0200

    spice: vdagent: return error code -1 on service install/uninstall failure #576625

diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index e8a773c..8139af4 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -44,9 +44,9 @@ class VDService {
 public:
     static VDService* get();
     ~VDService();
-    void run();
-    void install();
-    void uninstall();
+    bool run();
+    bool install();
+    bool uninstall();
 
 private:
     VDService();
@@ -162,24 +162,26 @@ VDService::~VDService()
     delete _log;
 }
 
-void VDService::run()
+bool VDService::run()
 {
     SERVICE_TABLE_ENTRY service_table[] = {{VD_SERVICE_NAME, main}, {0, 0}};
-    StartServiceCtrlDispatcher(service_table);
+    return !!StartServiceCtrlDispatcher(service_table);
 }
 
-void VDService::install()
+bool VDService::install()
 {
+    bool ret = false;
+
     SC_HANDLE service_control_manager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
     if (!service_control_manager) {
         printf("OpenSCManager failed\n");
-        return;
+        return false;
     }
     TCHAR path[_MAX_PATH + 1];
     if (!GetModuleFileName(0, path, sizeof(path) / sizeof(path[0]))) {
         printf("GetModuleFileName failed\n");
         CloseServiceHandle(service_control_manager);
-        return;
+        return false;
     }
     SC_HANDLE service = CreateService(service_control_manager, VD_SERVICE_NAME,
                                       VD_SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS,
@@ -194,27 +196,32 @@ void VDService::install()
         }
         CloseServiceHandle(service);
         printf("Service installed successfully\n");
+        ret = true;
     } else if (GetLastError() == ERROR_SERVICE_EXISTS) {
         printf("Service already exists\n");
+        ret = true;
     } else {
         printf("Service not installed successfully, error %d\n", GetLastError());
     }
     CloseServiceHandle(service_control_manager);
+    return ret;
 }
 
-void VDService::uninstall()
+bool VDService::uninstall()
 {
+    bool ret = false;
+
     SC_HANDLE service_control_manager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
     if (!service_control_manager) {
         printf("OpenSCManager failed\n");
-        return;
+        return false;
     }
     SC_HANDLE service = OpenService(service_control_manager, VD_SERVICE_NAME,
                                     SERVICE_QUERY_STATUS | DELETE);
     if (!service) {
         printf("OpenService failed\n");
         CloseServiceHandle(service_control_manager);
-        return;
+        return false;
     }
     SERVICE_STATUS status;
     if (!QueryServiceStatus(service, &status)) {
@@ -223,6 +230,7 @@ void VDService::uninstall()
         printf("Service is still running\n");
     } else if (DeleteService(service)) {
         printf("Service removed successfully\n");
+        ret = true;
     } else {
         switch (GetLastError()) {
         case ERROR_ACCESS_DENIED:
@@ -238,6 +246,7 @@ void VDService::uninstall()
     }
     CloseServiceHandle(service);
     CloseServiceHandle(service_control_manager);
+    return ret;
 }
 
 const char* session_events[] = {
@@ -1019,23 +1028,25 @@ void VDService::write_agent_control(uint32_t type, uint32_t opaque)
 
 int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
 {
+    bool success = false;
+
     if (!supported_system_version()) {
         printf("vdservice is not supported in this system version\n");
-        return 0;
+        return -1;
     }
     VDService* vdservice = VDService::get();
     if (argc > 1) {
         if (lstrcmpi(argv[1], TEXT("install")) == 0) {
-            vdservice->install();
+            success = vdservice->install();
         } else if (lstrcmpi(argv[1], TEXT("uninstall")) == 0) {
-            vdservice->uninstall();
+            success = vdservice->uninstall();
         } else {
             printf("Use: vdservice install / uninstall\n");
         }
     } else {
-        vdservice->run();
+        success = vdservice->run();
     }
     delete vdservice;
-    return 0;
+    return (success ? 0 : -1);
 }
 
commit ce07dc8a8d7c015f8da90618a6097f21f57d0311
Author: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
Date:   Mon Mar 1 16:46:33 2010 +0200

    spice: vdagent: upgrade solution & projects to vs2008

diff --git a/vdagent.sln b/vdagent.sln
index 1f0fc72..2622f2e 100644
--- a/vdagent.sln
+++ b/vdagent.sln
@@ -1,6 +1,6 @@
 
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdagent", "vdagent\vdagent.vcproj", "{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vdservice", "vdservice\vdservice.vcproj", "{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}"
diff --git a/vdagent/vdagent.vcproj b/vdagent/vdagent.vcproj
index ca65b07..f7f6bef 100644
--- a/vdagent/vdagent.vcproj
+++ b/vdagent/vdagent.vcproj
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="windows-1255"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8.00"
+	Version="9.00"
 	Name="vdagent"
 	ProjectGUID="{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}"
 	RootNamespace="redagent"
 	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
 		<Platform
@@ -50,7 +51,7 @@
 				RuntimeLibrary="1"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="4"
 			/>
 			<Tool
@@ -68,6 +69,8 @@
 				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
 				TargetMachine="1"
 			/>
 			<Tool
@@ -89,19 +92,15 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			Name="Debug|x64"
+			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
 			ConfigurationType="1"
 			CharacterSet="1"
-			WholeProgramOptimization="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -117,16 +116,19 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
+				Optimization="0"
 				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
-				AdditionalUsingDirectories=""
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
-				RuntimeLibrary="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -141,12 +143,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalDependencies="Version.lib"
-				LinkIncremental="1"
+				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -167,18 +169,16 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			Name="Release|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="1"
 			CharacterSet="1"
+			WholeProgramOptimization="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -194,19 +194,16 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="0"
 				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
+				AdditionalUsingDirectories=""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -221,10 +218,14 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalDependencies="Version.lib"
-				LinkIncremental="2"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
 				SubSystem="2"
-				TargetMachine="17"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -245,9 +246,6 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
@@ -283,7 +281,7 @@
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -303,6 +301,8 @@
 				SubSystem="2"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
 				TargetMachine="17"
 			/>
 			<Tool
@@ -324,9 +324,6 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
diff --git a/vdservice/vdservice.vcproj b/vdservice/vdservice.vcproj
index 8db43a9..4e70a8b 100644
--- a/vdservice/vdservice.vcproj
+++ b/vdservice/vdservice.vcproj
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="windows-1255"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8.00"
+	Version="9.00"
 	Name="vdservice"
 	ProjectGUID="{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}"
 	RootNamespace="redservice"
 	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
 	>
 	<Platforms>
 		<Platform
@@ -50,7 +51,7 @@
 				RuntimeLibrary="1"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="4"
 			/>
 			<Tool
@@ -68,6 +69,8 @@
 				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
 				TargetMachine="1"
 			/>
 			<Tool
@@ -89,19 +92,15 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
+			Name="Debug|x64"
+			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
 			ConfigurationType="1"
 			CharacterSet="1"
-			WholeProgramOptimization="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -117,15 +116,19 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
+				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
+				Optimization="0"
 				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
-				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
-				RuntimeLibrary="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -140,12 +143,12 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
-				LinkIncremental="1"
+				LinkIncremental="2"
 				GenerateDebugInformation="true"
 				SubSystem="1"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				TargetMachine="1"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="17"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -166,18 +169,16 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
 		<Configuration
-			Name="Debug|x64"
-			OutputDirectory="$(PlatformName)\$(ConfigurationName)"
-			IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+			Name="Release|Win32"
+			OutputDirectory="$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="1"
 			CharacterSet="1"
+			WholeProgramOptimization="1"
 			>
 			<Tool
 				Name="VCPreBuildEventTool"
@@ -193,19 +194,15 @@
 			/>
 			<Tool
 				Name="VCMIDLTool"
-				TargetEnvironment="3"
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="0"
 				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
-				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -220,10 +217,14 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
-				LinkIncremental="2"
+				LinkIncremental="1"
 				GenerateDebugInformation="true"
 				SubSystem="1"
-				TargetMachine="17"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
+				TargetMachine="1"
 			/>
 			<Tool
 				Name="VCALinkTool"
@@ -244,9 +245,6 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
@@ -281,7 +279,7 @@
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
-				Detect64BitPortabilityProblems="true"
+				Detect64BitPortabilityProblems="false"
 				DebugInformationFormat="3"
 			/>
 			<Tool
@@ -301,6 +299,8 @@
 				SubSystem="1"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
+				RandomizedBaseAddress="1"
+				DataExecutionPrevention="0"
 				TargetMachine="17"
 			/>
 			<Tool
@@ -322,9 +322,6 @@
 				Name="VCAppVerifierTool"
 			/>
 			<Tool
-				Name="VCWebDeploymentTool"
-			/>
-			<Tool
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
commit 8eafd5ef096a745968705c55b22ed3e64a3a8bf9
Author: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
Date:   Tue Feb 9 20:04:30 2010 +0200

    spice: vdagent: support x64 arch

diff --git a/vdagent/vdagent.vcproj b/vdagent/vdagent.vcproj
index f012bc4..ca65b07 100644
--- a/vdagent/vdagent.vcproj
+++ b/vdagent/vdagent.vcproj
@@ -330,6 +330,163 @@
 				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_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Version.lib"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<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"
+				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+				AdditionalUsingDirectories=""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Version.lib"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				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="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
diff --git a/vdservice/vdservice.vcproj b/vdservice/vdservice.vcproj
index 0616d08..8db43a9 100644
--- a/vdservice/vdservice.vcproj
+++ b/vdservice/vdservice.vcproj
@@ -328,6 +328,162 @@
 				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_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				LinkIncremental="2"
+				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="VCWebDeploymentTool"
+			/>
+			<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"
+				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				LinkIncremental="1"
+				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="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
commit c1b6d6a8a121d4536803abffbed2b265fb4c76fc
Author: Arnon Gilboa <agilboa at agilboa.usersys.redhat.com>
Date:   Tue Feb 9 20:04:30 2010 +0200

    spice: vdagent: support x64 arch

diff --git a/common/stdint.h b/common/stdint.h
index 9316d56..250efb5 100644
--- a/common/stdint.h
+++ b/common/stdint.h
@@ -136,10 +136,14 @@ typedef unsigned long long   uint_fast64_t;
 
 /* 7.18.1.4  Integer types capable of holding object pointers */
 
+#ifndef  _WIN64
+
 typedef int intptr_t;
 
 typedef unsigned uintptr_t;
 
+#endif
+
 
 
 /* 7.18.1.5  Greatest-width integer types */
diff --git a/vdagent.sln b/vdagent.sln
index afb6513..1f0fc72 100644
--- a/vdagent.sln
+++ b/vdagent.sln
@@ -8,17 +8,27 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
 		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.ActiveCfg = Debug|Win32
 		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|Win32.Build.0 = Debug|Win32
+		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.ActiveCfg = Debug|x64
+		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Debug|x64.Build.0 = Debug|x64
 		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.ActiveCfg = Release|Win32
 		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|Win32.Build.0 = Release|Win32
+		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.ActiveCfg = Release|x64
+		{CAD5A7E6-E9F5-4071-AFDA-25F76FDA5442}.Release|x64.Build.0 = Release|x64
 		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.ActiveCfg = Debug|Win32
 		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|Win32.Build.0 = Debug|Win32
+		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.ActiveCfg = Debug|x64
+		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Debug|x64.Build.0 = Debug|x64
 		{ADFE5E22-31D0-4343-AE9E-8102CC0051F9}.Release|Win32.ActiveCfg = Release|Win32
 		{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
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/vdagent/vdagent.vcproj b/vdagent/vdagent.vcproj
index 954f865..f012bc4 100644
--- a/vdagent/vdagent.vcproj
+++ b/vdagent/vdagent.vcproj
@@ -11,6 +11,9 @@
 		<Platform
 			Name="Win32"
 		/>
+		<Platform
+			Name="x64"
+		/>
 	</Platforms>
 	<ToolFiles>
 	</ToolFiles>
@@ -170,6 +173,163 @@
 				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_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Version.lib"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="17"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<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"
+				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+				AdditionalUsingDirectories=""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="Version.lib"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				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="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>
diff --git a/vdservice/vdservice.vcproj b/vdservice/vdservice.vcproj
index bad8505..0616d08 100644
--- a/vdservice/vdservice.vcproj
+++ b/vdservice/vdservice.vcproj
@@ -11,6 +11,9 @@
 		<Platform
 			Name="Win32"
 		/>
+		<Platform
+			Name="x64"
+		/>
 	</Platforms>
 	<ToolFiles>
 	</ToolFiles>
@@ -169,6 +172,162 @@
 				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_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				LinkIncremental="2"
+				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="VCWebDeploymentTool"
+			/>
+			<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"
+				AdditionalIncludeDirectories="..\common;$(SPICE_COMMON_DIR)"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE,_WIN32_WINNT=0x0501"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="true"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="WtsApi32.lib Userenv.lib Version.lib"
+				LinkIncremental="1"
+				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="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>


More information about the Spice-commits mailing list