[Spice-commits] 6 commits - common/vdlog.h vdservice/pci_vdi_port.cpp vdservice/pci_vdi_port.h vdservice/vdi_port.cpp vdservice/vdi_port.h vdservice/vdservice.cpp vdservice/vdservice.vcproj vdservice/virtio_vdi_port.cpp vdservice/virtio_vdi_port.h

Arnon Gilboa agilboa at kemper.freedesktop.org
Tue Jan 11 07:24:46 PST 2011


 common/vdlog.h                |    1 
 vdservice/pci_vdi_port.cpp    |  128 ++++++++++++++++
 vdservice/pci_vdi_port.h      |   59 +++++++
 vdservice/vdi_port.cpp        |  332 +++++++++++-------------------------------
 vdservice/vdi_port.h          |  149 +++++++++---------
 vdservice/vdservice.cpp       |  113 +++++++++-----
 vdservice/vdservice.vcproj    |   16 ++
 vdservice/virtio_vdi_port.cpp |  175 ++++++++++++++++++++++
 vdservice/virtio_vdi_port.h   |   33 ++++
 9 files changed, 655 insertions(+), 351 deletions(-)

New commits:
commit 24b9dd5ca9fae135f4ce036a9682d7826b0cfe30
Author: Alon Levy <alevy at redhat.com>
Date:   Mon Jan 3 10:47:33 2011 +0200

    vdservice: s/fill_events(HANDLE *handle)/fill_events(HANDLE* handles)/ + unix2dos

diff --git a/vdservice/pci_vdi_port.cpp b/vdservice/pci_vdi_port.cpp
index b055c5a..d07eab7 100644
--- a/vdservice/pci_vdi_port.cpp
+++ b/vdservice/pci_vdi_port.cpp
@@ -1,128 +1,128 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "pci_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
-
-#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
-    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-
-#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)
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-PCIVDIPort::PCIVDIPort()
-    : _handle (INVALID_HANDLE_VALUE)
-    , _event (NULL)
-{
-}
-
-PCIVDIPort::~PCIVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_event) {
-        CloseHandle(_event);
-    }
-}
-
-void PCIVDIPort::fill_events(HANDLE *handle) {
-    handle[PCI_VDI_PORT_EVENT] = _event;
-}
-
-bool PCIVDIPort::init()
-{
-    DWORD io_ret_len;
-    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
-                         OPEN_EXISTING, 0, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() failed: %u", GetLastError());
-        return false;
-    }
-    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_event == 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());
-        return false;
-    }
-    return true;
-}
-
-int PCIVDIPort::write()
-{
-    int size;
-    int n;
-
-    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 (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
-    return n;
-}
-
-int PCIVDIPort::read()
-{
-    int size;
-    int n;
-
-    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 (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
-        return handle_error();
-    }
-    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
-    return n;
-}
-
-void PCIVDIPort::handle_event(int event)
-{
-    // do nothing - the event merely serves to wake us up, then we call read/write
-    // at VDService::execute start of while(_running) loop.
-}
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "pci_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
+
+#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
+    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#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)
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+PCIVDIPort::PCIVDIPort()
+    : _handle (INVALID_HANDLE_VALUE)
+    , _event (NULL)
+{
+}
+
+PCIVDIPort::~PCIVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_event) {
+        CloseHandle(_event);
+    }
+}
+
+void PCIVDIPort::fill_events(HANDLE* handles) {
+    handles[PCI_VDI_PORT_EVENT] = _event;
+}
+
+bool PCIVDIPort::init()
+{
+    DWORD io_ret_len;
+    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                         OPEN_EXISTING, 0, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() failed: %u", GetLastError());
+        return false;
+    }
+    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_event == 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());
+        return false;
+    }
+    return true;
+}
+
+int PCIVDIPort::write()
+{
+    int size;
+    int n;
+
+    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 (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
+    return n;
+}
+
+int PCIVDIPort::read()
+{
+    int size;
+    int n;
+
+    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 (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
+    return n;
+}
+
+void PCIVDIPort::handle_event(int event)
+{
+    // do nothing - the event merely serves to wake us up, then we call read/write
+    // at VDService::execute start of while(_running) loop.
+}
diff --git a/vdservice/pci_vdi_port.h b/vdservice/pci_vdi_port.h
index d9b6d67..caa990f 100644
--- a/vdservice/pci_vdi_port.h
+++ b/vdservice/pci_vdi_port.h
@@ -40,7 +40,7 @@ public:
     virtual int write();
     virtual int read();
     virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE* handle);
+    virtual void fill_events(HANDLE* handles);
     virtual void handle_event(int event);
 
 private:
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index b5c6f46..50c4d29 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -1,33 +1,33 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_VDI_PORT
-#define _H_VDI_PORT
-
-#include <windows.h>
-#include <stdint.h>
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-#define BUF_SIZE    (1024 * 1024)
-
-#define VDI_PORT_BLOCKED    0
-#define VDI_PORT_RESET      -1
-#define VDI_PORT_ERROR      -2
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_VDI_PORT
+#define _H_VDI_PORT
+
+#include <windows.h>
+#include <stdint.h>
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+#define BUF_SIZE    (1024 * 1024)
+
+#define VDI_PORT_BLOCKED    0
+#define VDI_PORT_RESET      -1
+#define VDI_PORT_ERROR      -2
 
 // Ring notes:
 // _end is one after the end of data
@@ -36,40 +36,40 @@
 // _start-1 is never used
 // ring_write & read on right side of the ring (update _end)
 // ring_read & write from left (update _start)
-
-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();
-    virtual ~VDIPort() {}
-
-    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();
-
-    virtual const char *name() = 0;
-    virtual bool init() = 0;
-    virtual unsigned get_num_events() = 0;
-    virtual void fill_events(HANDLE *handle) = 0;
-    virtual void handle_event(int event) = 0;
-    virtual int write() = 0;
-    virtual int read() = 0;
-
-protected:
-    int handle_error();
-
-    VDIPortBuffer _write;
-    VDIPortBuffer _read;
-};
-
-#endif
+
+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();
+    virtual ~VDIPort() {}
+
+    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();
+
+    virtual const char *name() = 0;
+    virtual bool init() = 0;
+    virtual unsigned get_num_events() = 0;
+    virtual void fill_events(HANDLE* handles) = 0;
+    virtual void handle_event(int event) = 0;
+    virtual int write() = 0;
+    virtual int read() = 0;
+
+protected:
+    int handle_error();
+
+    VDIPortBuffer _write;
+    VDIPortBuffer _read;
+};
+
+#endif
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
index bbdd59e..ce4d80a 100644
--- a/vdservice/virtio_vdi_port.cpp
+++ b/vdservice/virtio_vdi_port.cpp
@@ -1,56 +1,56 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "virtio_vdi_port.h"
-#include "vdlog.h"
-
-#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
-
-// Current limitation of virtio-serial windows driver (RHBZ 617000)
-#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
-
-VirtioVDIPort* VirtioVDIPort::_singleton;
-
-VirtioVDIPort::VirtioVDIPort()
-    : VDIPort()
-    , _handle (INVALID_HANDLE_VALUE)
-{
-    _singleton = this;
-}
-
-VirtioVDIPort::~VirtioVDIPort()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_read.overlap.hEvent) {
-        CloseHandle(_read.overlap.hEvent);
-    }
-    if (_write.overlap.hEvent) {
-        CloseHandle(_write.overlap.hEvent);
-    }
-}
-
-void VirtioVDIPort::fill_events(HANDLE *handle) {
-    handle[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
-    handle[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
-}
-
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "virtio_vdi_port.h"
+#include "vdlog.h"
+
+#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
+
+// Current limitation of virtio-serial windows driver (RHBZ 617000)
+#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
+
+VirtioVDIPort* VirtioVDIPort::_singleton;
+
+VirtioVDIPort::VirtioVDIPort()
+    : VDIPort()
+    , _handle (INVALID_HANDLE_VALUE)
+{
+    _singleton = this;
+}
+
+VirtioVDIPort::~VirtioVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_read.overlap.hEvent) {
+        CloseHandle(_read.overlap.hEvent);
+    }
+    if (_write.overlap.hEvent) {
+        CloseHandle(_write.overlap.hEvent);
+    }
+}
+
+void VirtioVDIPort::fill_events(HANDLE* handles) {
+    handles[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
+    handles[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
+}
+
 void VirtioVDIPort::handle_event(int event) {
     switch (event) {
         case VIRTIO_VDI_PORT_EVENT_WRITE:
@@ -62,114 +62,114 @@ void VirtioVDIPort::handle_event(int event) {
         default:
             vd_printf("ERROR: unexpected event %d", event);
     }
-}
-
-bool VirtioVDIPort::init()
-{
-    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
-                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
-        return false;
-    }
-    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_write.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %u", GetLastError());
-        return false;
-    }
-    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_read.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %u", GetLastError());
-        return false;
-    }
-    return true;
-}
-
-int VirtioVDIPort::write()
-{
-    int size;
-    int ret;
-
-    //FIXME: return VDI_PORT_NO_DATA
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    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();
-        }
-    }
-    ret = _write.bytes;
-    _write.bytes = 0;
-    return ret;
-}
-
-void VirtioVDIPort::write_completion()
-{
-    DWORD bytes;
-
-    if (!_write.pending) {
-        return;
-    }
-    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;
-}
-
-int VirtioVDIPort::read()
-{
-    int size;
-    int ret;
-
-    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();
-        }
-    }
-    ret = _read.bytes;
-    _read.bytes = 0;
-    return ret;
-}
-
-void VirtioVDIPort::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 + bytes) % BUF_SIZE;
-    _read.bytes = bytes;
-    _read.pending = false;
-}
+}
+
+bool VirtioVDIPort::init()
+{
+    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
+        return false;
+    }
+    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_write.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %u", GetLastError());
+        return false;
+    }
+    _read.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_read.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %u", GetLastError());
+        return false;
+    }
+    return true;
+}
+
+int VirtioVDIPort::write()
+{
+    int size;
+    int ret;
+
+    //FIXME: return VDI_PORT_NO_DATA
+    if (_write.start == _write.end) {
+        return 0;
+    }
+    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();
+        }
+    }
+    ret = _write.bytes;
+    _write.bytes = 0;
+    return ret;
+}
+
+void VirtioVDIPort::write_completion()
+{
+    DWORD bytes;
+
+    if (!_write.pending) {
+        return;
+    }
+    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;
+}
+
+int VirtioVDIPort::read()
+{
+    int size;
+    int ret;
+
+    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();
+        }
+    }
+    ret = _read.bytes;
+    _read.bytes = 0;
+    return ret;
+}
+
+void VirtioVDIPort::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 + bytes) % BUF_SIZE;
+    _read.bytes = bytes;
+    _read.pending = false;
+}
diff --git a/vdservice/virtio_vdi_port.h b/vdservice/virtio_vdi_port.h
index 04d3412..15b6811 100644
--- a/vdservice/virtio_vdi_port.h
+++ b/vdservice/virtio_vdi_port.h
@@ -16,7 +16,7 @@ public:
     virtual const char *name() { return "VirtioVDIPort"; }
     virtual bool init();
     virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
-    virtual void fill_events(HANDLE *handle);
+    virtual void fill_events(HANDLE* handles);
     virtual void handle_event(int event);
     virtual int write();
     virtual int read();
@@ -30,4 +30,4 @@ private:
     HANDLE _handle;
 };
 
-#endif //_H_VIRTIO_VDI_PORT
\ No newline at end of file
+#endif //_H_VIRTIO_VDI_PORT
commit db2d109d692fa2e00dfa69eb12bcc30505e0041f
Author: Alon Levy <alevy at redhat.com>
Date:   Sun Jan 2 17:31:26 2011 +0200

    vdservice/vdi_port refactor: cosmetic changes
    
     * move comment about ring to the proper file, vdi_port.h
     * introduce enums for EVENT indices (0,1 for Virtio, 0 for PCI)
     * move fill_events to cpp (leave the single lines inline).

diff --git a/vdservice/pci_vdi_port.cpp b/vdservice/pci_vdi_port.cpp
index 3baefd9..b055c5a 100644
--- a/vdservice/pci_vdi_port.cpp
+++ b/vdservice/pci_vdi_port.cpp
@@ -52,6 +52,10 @@ PCIVDIPort::~PCIVDIPort()
     }
 }
 
+void PCIVDIPort::fill_events(HANDLE *handle) {
+    handle[PCI_VDI_PORT_EVENT] = _event;
+}
+
 bool PCIVDIPort::init()
 {
     DWORD io_ret_len;
diff --git a/vdservice/pci_vdi_port.h b/vdservice/pci_vdi_port.h
index 40a0589..d9b6d67 100644
--- a/vdservice/pci_vdi_port.h
+++ b/vdservice/pci_vdi_port.h
@@ -1,54 +1,59 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_PCI_VDI_PORT
-#define _H_PCI_VDI_PORT
-
-#include "vdi_port.h"
-
-#define BUF_READ    (1 << 0)
-#define BUF_WRITE   (1 << 1)
-#define BUF_ALL     (BUF_READ | BUF_WRITE)
-
-class PCIVDIPort : public VDIPort {
-public:
-    PCIVDIPort();
-    ~PCIVDIPort();
-    virtual bool init();
-    virtual const char *name() { return "PCIVDIPort"; }
-    virtual int write();
-    virtual int read();
-    virtual unsigned get_num_events() { return 1; }
-    virtual void fill_events(HANDLE *handle) {
-        handle[0] = _event;
-    }
-    virtual void handle_event(int event);
-
-private:
-    HANDLE _handle;
-    HANDLE _event;
-};
-
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-#endif
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_PCI_VDI_PORT
+#define _H_PCI_VDI_PORT
+
+#include "vdi_port.h"
+
+#define BUF_READ    (1 << 0)
+#define BUF_WRITE   (1 << 1)
+#define BUF_ALL     (BUF_READ | BUF_WRITE)
+
+enum {
+    PCI_VDI_PORT_EVENT = 0,
+    PCI_VDI_PORT_EVENT_COUNT
+};
+
+class PCIVDIPort : public VDIPort {
+public:
+    PCIVDIPort();
+    ~PCIVDIPort();
+    virtual bool init();
+    virtual const char *name() {
+        return "PCIVDIPort";
+    }
+    virtual int write();
+    virtual int read();
+    virtual unsigned get_num_events() { return PCI_VDI_PORT_EVENT_COUNT; }
+    virtual void fill_events(HANDLE* handle);
+    virtual void handle_event(int event);
+
+private:
+    HANDLE _handle;
+    HANDLE _event;
+};
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
+
+#endif
diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
index 9638dc0..60bd0ef 100644
--- a/vdservice/vdi_port.cpp
+++ b/vdservice/vdi_port.cpp
@@ -74,17 +74,17 @@ size_t VDIPort::ring_read(void* buf, size_t size)
     _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
     return n + m;
 }
-
-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;
-        return VDI_PORT_RESET;
-    default:
-        vd_printf("port io failed: %u", GetLastError());
-        return VDI_PORT_ERROR;
-    }
-}
+
+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;
+        return VDI_PORT_RESET;
+    default:
+        vd_printf("port io failed: %u", GetLastError());
+        return VDI_PORT_ERROR;
+    }
+}
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index 63b04bb..b5c6f46 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -28,6 +28,14 @@
 #define VDI_PORT_BLOCKED    0
 #define VDI_PORT_RESET      -1
 #define VDI_PORT_ERROR      -2
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
 
 typedef struct VDIPortBuffer {
     OVERLAPPED overlap;
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
index 4f24a26..bbdd59e 100644
--- a/vdservice/virtio_vdi_port.cpp
+++ b/vdservice/virtio_vdi_port.cpp
@@ -46,6 +46,24 @@ VirtioVDIPort::~VirtioVDIPort()
     }
 }
 
+void VirtioVDIPort::fill_events(HANDLE *handle) {
+    handle[VIRTIO_VDI_PORT_EVENT_WRITE] = _write.overlap.hEvent;
+    handle[VIRTIO_VDI_PORT_EVENT_READ] = _read.overlap.hEvent;
+}
+
+void VirtioVDIPort::handle_event(int event) {
+    switch (event) {
+        case VIRTIO_VDI_PORT_EVENT_WRITE:
+            write_completion();
+            break;
+        case VIRTIO_VDI_PORT_EVENT_READ:
+            read_completion();
+            break;
+        default:
+            vd_printf("ERROR: unexpected event %d", event);
+    }
+}
+
 bool VirtioVDIPort::init()
 {
     _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
diff --git a/vdservice/virtio_vdi_port.h b/vdservice/virtio_vdi_port.h
index 6738804..04d3412 100644
--- a/vdservice/virtio_vdi_port.h
+++ b/vdservice/virtio_vdi_port.h
@@ -3,23 +3,21 @@
 
 #include "vdi_port.h"
 
+enum {
+    VIRTIO_VDI_PORT_EVENT_WRITE=0,
+    VIRTIO_VDI_PORT_EVENT_READ,
+    VIRTIO_VDI_PORT_EVENT_COUNT
+};
+
 class VirtioVDIPort : public VDIPort {
 public:
     VirtioVDIPort();
     ~VirtioVDIPort();
-    virtual const char *name() { return "VirtioVDIPort"; }
+    virtual const char *name() { return "VirtioVDIPort"; }
     virtual bool init();
-    virtual unsigned get_num_events() { return 2; }
-    virtual void fill_events(HANDLE *handle) {
-        handle[0] = _write.overlap.hEvent;
-        handle[1] = _read.overlap.hEvent;
-    }
-    virtual void handle_event(int event) {
-        switch (event) {
-            case 0: write_completion(); break;
-            case 1: read_completion(); break;
-        }
-    }
+    virtual unsigned get_num_events() { return VIRTIO_VDI_PORT_EVENT_COUNT; }
+    virtual void fill_events(HANDLE *handle);
+    virtual void handle_event(int event);
     virtual int write();
     virtual int read();
 
@@ -32,13 +30,4 @@ private:
     HANDLE _handle;
 };
 
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
-
 #endif //_H_VIRTIO_VDI_PORT
\ No newline at end of file
commit 0f92cbea70efc5366465fdb52e44fd4c727b45ac
Author: Alon Levy <alevy at redhat.com>
Date:   Thu Dec 30 13:48:52 2010 +0200

    vdi_port refactor: introduce old pci_vdi_port
    
    This patch is a little dirty due to EOL convertion to windows format.
    
     + add pci_vdi_port with PCIVDIPort taken from last commit before
      changing to virtio-serial (a17ccbf323768c3cb977f0f062366ba7cf7f19db)
     + move handle_error to VDIPort (identical in VIRTIOVDIPort and PCIVDIPort)
     + make VDService create first a virtio, then init, the pci, then init,
      stopping when the first init succeeds, and reporting to log which was
      created.

diff --git a/common/vdlog.h b/common/vdlog.h
index 419248a..bb2eb28 100644
--- a/common/vdlog.h
+++ b/common/vdlog.h
@@ -18,6 +18,7 @@
 #ifndef _H_VDLOG
 #define _H_VDLOG
 
+#include <stdio.h>
 #include <tchar.h>
 #include <crtdbg.h>
 #include <windows.h>
diff --git a/vdservice/pci_vdi_port.cpp b/vdservice/pci_vdi_port.cpp
new file mode 100644
index 0000000..3baefd9
--- /dev/null
+++ b/vdservice/pci_vdi_port.cpp
@@ -0,0 +1,124 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "pci_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
+
+#define CTL_CODE(DeviceType, Function, Method, Access) (                   \
+    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#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)
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+PCIVDIPort::PCIVDIPort()
+    : _handle (INVALID_HANDLE_VALUE)
+    , _event (NULL)
+{
+}
+
+PCIVDIPort::~PCIVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_event) {
+        CloseHandle(_event);
+    }
+}
+
+bool PCIVDIPort::init()
+{
+    DWORD io_ret_len;
+    _handle = CreateFile(VDI_PORT_DEV_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+                         OPEN_EXISTING, 0, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() failed: %u", GetLastError());
+        return false;
+    }
+    _event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_event == 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());
+        return false;
+    }
+    return true;
+}
+
+int PCIVDIPort::write()
+{
+    int size;
+    int n;
+
+    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 (!WriteFile(_handle, _write.start, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _write.start = _write.ring + (_write.start - _write.ring + n) % BUF_SIZE;
+    return n;
+}
+
+int PCIVDIPort::read()
+{
+    int size;
+    int n;
+
+    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 (!ReadFile(_handle, _read.end, size, (LPDWORD)&n, NULL)) {
+        return handle_error();
+    }
+    _read.end = _read.ring + (_read.end - _read.ring + n) % BUF_SIZE;
+    return n;
+}
+
+void PCIVDIPort::handle_event(int event)
+{
+    // do nothing - the event merely serves to wake us up, then we call read/write
+    // at VDService::execute start of while(_running) loop.
+}
diff --git a/vdservice/pci_vdi_port.h b/vdservice/pci_vdi_port.h
new file mode 100644
index 0000000..40a0589
--- /dev/null
+++ b/vdservice/pci_vdi_port.h
@@ -0,0 +1,54 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_PCI_VDI_PORT
+#define _H_PCI_VDI_PORT
+
+#include "vdi_port.h"
+
+#define BUF_READ    (1 << 0)
+#define BUF_WRITE   (1 << 1)
+#define BUF_ALL     (BUF_READ | BUF_WRITE)
+
+class PCIVDIPort : public VDIPort {
+public:
+    PCIVDIPort();
+    ~PCIVDIPort();
+    virtual bool init();
+    virtual const char *name() { return "PCIVDIPort"; }
+    virtual int write();
+    virtual int read();
+    virtual unsigned get_num_events() { return 1; }
+    virtual void fill_events(HANDLE *handle) {
+        handle[0] = _event;
+    }
+    virtual void handle_event(int event);
+
+private:
+    HANDLE _handle;
+    HANDLE _event;
+};
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
+
+#endif
diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
index f9fbcdf..9638dc0 100644
--- a/vdservice/vdi_port.cpp
+++ b/vdservice/vdi_port.cpp
@@ -1,76 +1,90 @@
+#include "vdlog.h"
 #include "vdi_port.h"
 
 VDIPort::VDIPort()
 {
-    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
-    _write.start = _write.end = _write.ring;
-    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
-    _read.start = _read.end = _read.ring;
-}
-
-
-size_t VDIPort::read_ring_size()
-{
-    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
-}
-
-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 n;
-
-    if (size > free_size) {
-        size = free_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);
-        if (size > n) {
-            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
-        }
-    }
-    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
-    return 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;
-}
+    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
+    _write.start = _write.end = _write.ring;
+    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
+    _read.start = _read.end = _read.ring;
+}
+
+size_t VDIPort::read_ring_size()
+{
+    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
+}
+
+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 n;
+
+    if (size > free_size) {
+        size = free_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);
+        if (size > n) {
+            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
+        }
+    }
+    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
+    return 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)
+{
+    size_t n;
+    size_t m = 0;
+
+    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);
+    } else {
+        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);
+        }
+    }
+    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
+    return n + m;
+}
 
-size_t VDIPort::ring_read(void* buf, size_t size)
+int VDIPort::handle_error()
 {
-    size_t n;
-    size_t m = 0;
-
-    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);
-    } else {
-        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);
-        }
+    switch (GetLastError()) {
+    case ERROR_CONNECTION_INVALID:
+        vd_printf("port reset");
+        _write.start = _write.end = _write.ring;
+        _read.start = _read.end = _read.ring;
+        return VDI_PORT_RESET;
+    default:
+        vd_printf("port io failed: %u", GetLastError());
+        return VDI_PORT_ERROR;
     }
-    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
-    return n + m;
 }
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index cc4cb53..63b04bb 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -49,6 +49,7 @@ public:
     size_t read_ring_size();
     size_t read_ring_continuous_remaining_size();
 
+    virtual const char *name() = 0;
     virtual bool init() = 0;
     virtual unsigned get_num_events() = 0;
     virtual void fill_events(HANDLE *handle) = 0;
@@ -57,6 +58,8 @@ public:
     virtual int read() = 0;
 
 protected:
+    int handle_error();
+
     VDIPortBuffer _write;
     VDIPortBuffer _read;
 };
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 7b0cadb..175587c 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -23,6 +23,7 @@
 #include <tlhelp32.h>
 #include "vdcommon.h"
 #include "virtio_vdi_port.h"
+#include "pci_vdi_port.h"
 
 //#define DEBUG_VDSERVICE
 
@@ -401,6 +402,16 @@ VOID WINAPI VDService::main(DWORD argc, TCHAR* argv[])
 #endif //DEBUG_VDSERVICE
 }
 
+VDIPort *create_virtio_vdi_port()
+{
+    return new VirtioVDIPort();
+}
+
+VDIPort *create_pci_vdi_port()
+{
+    return new PCIVDIPort();
+}
+
 bool VDService::execute()
 {
     SECURITY_ATTRIBUTES sec_attr;
@@ -434,12 +445,25 @@ bool VDService::execute()
         CloseHandle(pipe);
         return false;
     }
-    _vdi_port = new VirtioVDIPort();
-    if (!_vdi_port->init()) {
-        delete _vdi_port;
+
+    bool init = false;
+    {
+        VDIPort* (*creators[])(void) = { create_virtio_vdi_port, create_pci_vdi_port };
+        for (int i = 0 ; i < sizeof(creators)/sizeof(creators[0]); ++i) {
+            _vdi_port = creators[i]();
+            init = _vdi_port->init();
+            if (init) {
+                break;
+            }
+            delete _vdi_port;
+        }
+    }
+    if (!init) {
+        vd_printf("Failed to create VDIPort instance");
         CloseHandle(pipe);
         return false;
     }
+    vd_printf("created %s", _vdi_port->name());
     _events_count = VD_STATIC_EVENTS_COUNT + _vdi_port->get_num_events() + 1 /*for agent*/;
     _events = new HANDLE[_events_count];
     _events_vdi_port_base = VD_STATIC_EVENTS_COUNT;
diff --git a/vdservice/vdservice.vcproj b/vdservice/vdservice.vcproj
index 32ec7c8..bbb1b75 100644
--- a/vdservice/vdservice.vcproj
+++ b/vdservice/vdservice.vcproj
@@ -335,6 +335,10 @@
 			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
 			>
 			<File
+				RelativePath=".\pci_vdi_port.h"
+				>
+			</File>
+			<File
 				RelativePath=".\resource.h"
 				>
 			</File>
@@ -350,6 +354,10 @@
 				RelativePath="..\common\vdlog.h"
 				>
 			</File>
+			<File
+				RelativePath=".\virtio_vdi_port.h"
+				>
+			</File>
 		</Filter>
 		<Filter
 			Name="Resource Files"
@@ -367,6 +375,10 @@
 			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
 			>
 			<File
+				RelativePath=".\pci_vdi_port.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\vdi_port.cpp"
 				>
 			</File>
@@ -378,6 +390,10 @@
 				RelativePath=".\vdservice.cpp"
 				>
 			</File>
+			<File
+				RelativePath=".\virtio_vdi_port.cpp"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
index 278a88b..4f24a26 100644
--- a/vdservice/virtio_vdi_port.cpp
+++ b/vdservice/virtio_vdi_port.cpp
@@ -48,7 +48,6 @@ VirtioVDIPort::~VirtioVDIPort()
 
 bool VirtioVDIPort::init()
 {
-    vd_printf("creating VirtioVDIPort");
     _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
                          OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     if (_handle == INVALID_HANDLE_VALUE) {
@@ -156,17 +155,3 @@ void VirtioVDIPort::read_completion()
     _read.bytes = bytes;
     _read.pending = false;
 }
-
-int VirtioVDIPort::handle_error()
-{
-    switch (GetLastError()) {
-    case ERROR_CONNECTION_INVALID:
-        vd_printf("port reset");
-        _write.start = _write.end = _write.ring;
-        _read.start = _read.end = _read.ring;
-        return VDI_PORT_RESET;
-    default:
-        vd_printf("port io failed: %u", GetLastError());
-        return VDI_PORT_ERROR;
-    }
-}
commit 935330f996535f7d59963978fc8fdb17bf1d75cb
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Dec 29 17:54:23 2010 +0200

    vdi_port refactor: move ring handling to VDIPort, split h file, remove some debug prints

diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
new file mode 100644
index 0000000..f9fbcdf
--- /dev/null
+++ b/vdservice/vdi_port.cpp
@@ -0,0 +1,76 @@
+#include "vdi_port.h"
+
+VDIPort::VDIPort()
+{
+    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
+    _write.start = _write.end = _write.ring;
+    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
+    _read.start = _read.end = _read.ring;
+}
+
+
+size_t VDIPort::read_ring_size()
+{
+    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
+}
+
+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 n;
+
+    if (size > free_size) {
+        size = free_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);
+        if (size > n) {
+            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
+        }
+    }
+    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
+    return 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)
+{
+    size_t n;
+    size_t m = 0;
+
+    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);
+    } else {
+        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);
+        }
+    }
+    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
+    return n + m;
+}
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index 2d2b2d2..cc4cb53 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -21,6 +21,8 @@
 #include <windows.h>
 #include <stdint.h>
 
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
 #define BUF_SIZE    (1024 * 1024)
 
 #define VDI_PORT_BLOCKED    0
@@ -38,62 +40,25 @@ typedef struct VDIPortBuffer {
 
 class VDIPort {
 public:
+    VDIPort();
     virtual ~VDIPort() {}
+
+    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();
+
     virtual bool init() = 0;
-    virtual size_t ring_write(const void* buf, size_t size) = 0;
-    virtual size_t write_ring_free_space() = 0;
-    virtual size_t ring_read(void* buf, size_t size) = 0;
-    virtual size_t read_ring_size() = 0;
-    virtual size_t read_ring_continuous_remaining_size() = 0;
     virtual unsigned get_num_events() = 0;
     virtual void fill_events(HANDLE *handle) = 0;
     virtual void handle_event(int event) = 0;
     virtual int write() = 0;
     virtual int read() = 0;
-};
 
-class VirtioVDIPort : public VDIPort {
-public:
-    VirtioVDIPort();
-    ~VirtioVDIPort();
-    virtual bool init();
-    virtual size_t ring_write(const void* buf, size_t size);
-    virtual size_t write_ring_free_space();
-    virtual size_t ring_read(void* buf, size_t size);
-    virtual size_t read_ring_size();
-    virtual size_t read_ring_continuous_remaining_size();
-    virtual unsigned get_num_events() { return 2; }
-    virtual void fill_events(HANDLE *handle) {
-        handle[0] = _write.overlap.hEvent;
-        handle[1] = _read.overlap.hEvent;
-    }
-    virtual void handle_event(int event) {
-        switch (event) {
-            case 0: write_completion(); break;
-            case 1: read_completion(); break;
-        }
-    }
-    virtual int write();
-    virtual int read();
-
-private:
-    void write_completion();
-    void read_completion();
-    int handle_error();
-
-private:
-    static VirtioVDIPort* _singleton;
-    HANDLE _handle;
+protected:
     VDIPortBuffer _write;
     VDIPortBuffer _read;
 };
 
-// Ring notes:
-// _end is one after the end of data
-// _start==_end means empty ring
-// _start-1==_end (modulo) means full ring
-// _start-1 is never used
-// ring_write & read on right side of the ring (update _end)
-// ring_read & write from left (update _start)
-
 #endif
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 4c7785b..7b0cadb 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <tlhelp32.h>
 #include "vdcommon.h"
-#include "vdi_port.h"
+#include "virtio_vdi_port.h"
 
 //#define DEBUG_VDSERVICE
 
@@ -450,8 +450,6 @@ bool VDService::execute()
     _events[VD_EVENT_CONTROL] = _control_event;
     _events[VD_EVENT_LOGON] = _logon_event;
     _agent_proc_info.hProcess;
-    vd_printf("Calling fill_events");
-    vd_printf("&_events[VD_ENVETS_COUNT] == %p", &_events[VD_STATIC_EVENTS_COUNT]);
     _vdi_port->fill_events(&_events[_events_vdi_port_base]);
     _chunk_size = _chunk_port = 0;
     read_pipe();
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
index 8a7cf19..278a88b 100644
--- a/vdservice/virtio_vdi_port.cpp
+++ b/vdservice/virtio_vdi_port.cpp
@@ -16,7 +16,7 @@
 */
 
 #include "stdio.h"
-#include "vdi_port.h"
+#include "virtio_vdi_port.h"
 #include "vdlog.h"
 
 #define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
@@ -24,17 +24,12 @@
 // Current limitation of virtio-serial windows driver (RHBZ 617000)
 #define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
 
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
 VirtioVDIPort* VirtioVDIPort::_singleton;
 
 VirtioVDIPort::VirtioVDIPort()
-    : _handle (INVALID_HANDLE_VALUE)
+    : VDIPort()
+    , _handle (INVALID_HANDLE_VALUE)
 {
-    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
-    _write.start = _write.end = _write.ring;
-    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
-    _read.start = _read.end = _read.ring;
     _singleton = this;
 }
 
@@ -53,6 +48,7 @@ VirtioVDIPort::~VirtioVDIPort()
 
 bool VirtioVDIPort::init()
 {
+    vd_printf("creating VirtioVDIPort");
     _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
                          OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     if (_handle == INVALID_HANDLE_VALUE) {
@@ -72,32 +68,6 @@ bool VirtioVDIPort::init()
     return true;
 }
 
-size_t VirtioVDIPort::write_ring_free_space()
-{
-    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
-}
-
-size_t VirtioVDIPort::ring_write(const void* buf, size_t 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);
-    } else {
-        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);
-        }
-    }
-    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
-    return size;
-}
-
 int VirtioVDIPort::write()
 {
     int size;
@@ -142,46 +112,6 @@ void VirtioVDIPort::write_completion()
     _write.pending = false;
 }
 
-size_t VirtioVDIPort::read_ring_size()
-{
-    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
-}
-
-size_t VirtioVDIPort::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 VirtioVDIPort::ring_read(void* buf, size_t size)
-{
-    size_t n;
-    size_t m = 0;
-
-    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);
-    } else {
-        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);
-        }
-    }
-    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
-    return n + m;
-}
-
 int VirtioVDIPort::read()
 {
     int size;
diff --git a/vdservice/virtio_vdi_port.h b/vdservice/virtio_vdi_port.h
new file mode 100644
index 0000000..6738804
--- /dev/null
+++ b/vdservice/virtio_vdi_port.h
@@ -0,0 +1,44 @@
+#ifndef _H_VIRTIO_VDI_PORT
+#define _H_VIRTIO_VDI_PORT
+
+#include "vdi_port.h"
+
+class VirtioVDIPort : public VDIPort {
+public:
+    VirtioVDIPort();
+    ~VirtioVDIPort();
+    virtual const char *name() { return "VirtioVDIPort"; }
+    virtual bool init();
+    virtual unsigned get_num_events() { return 2; }
+    virtual void fill_events(HANDLE *handle) {
+        handle[0] = _write.overlap.hEvent;
+        handle[1] = _read.overlap.hEvent;
+    }
+    virtual void handle_event(int event) {
+        switch (event) {
+            case 0: write_completion(); break;
+            case 1: read_completion(); break;
+        }
+    }
+    virtual int write();
+    virtual int read();
+
+private:
+    void write_completion();
+    void read_completion();
+
+private:
+    static VirtioVDIPort* _singleton;
+    HANDLE _handle;
+};
+
+// Ring notes:
+// _end is one after the end of data
+// _start==_end means empty ring
+// _start-1==_end (modulo) means full ring
+// _start-1 is never used
+// ring_write & read on right side of the ring (update _end)
+// ring_read & write from left (update _start)
+
+
+#endif //_H_VIRTIO_VDI_PORT
\ No newline at end of file
commit 904b0860b331832d9c274731ac65709df4932242
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Dec 29 17:42:14 2010 +0200

    vdi_port refactor: introduce interface
    
    make VDIPort an abstract class.
    rename old VDIPort VirtioVDIPort.
    h file for virtio_vdi_port will be introduced later.

diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
deleted file mode 100644
index f4dfaeb..0000000
--- a/vdservice/vdi_port.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "stdio.h"
-#include "vdi_port.h"
-#include "vdlog.h"
-
-#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
-
-// Current limitation of virtio-serial windows driver (RHBZ 617000)
-#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
-
-#define MIN(a, b) ((a) > (b) ? (b) : (a))
-
-VDIPort* VDIPort::_singleton;
-
-VDIPort::VDIPort()
-    : _handle (INVALID_HANDLE_VALUE)
-{
-    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()
-{
-    if (_handle != INVALID_HANDLE_VALUE) {
-        CloseHandle(_handle);
-    }
-    if (_read.overlap.hEvent) {
-        CloseHandle(_read.overlap.hEvent);
-    }
-    if (_write.overlap.hEvent) {
-        CloseHandle(_write.overlap.hEvent);
-    }
-}
-
-bool VDIPort::init()
-{
-    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
-                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
-    if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
-        return false;
-    }
-    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if (_write.overlap.hEvent == NULL) {
-        vd_printf("CreateEvent() failed: %u", GetLastError());
-        return false;
-    }
-    _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 n;
-
-    if (size > free_size) {
-        size = free_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);
-        if (size > n) {
-            memcpy(_write.ring, (uint8_t*)buf + n, size - n);
-        }
-    }
-    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
-    return size;
-}
-
-int VDIPort::write()
-{
-    int size;
-    int ret;
-
-    //FIXME: return VDI_PORT_NO_DATA
-    if (_write.start == _write.end) {
-        return 0;
-    }
-    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();
-        }
-    }
-    ret = _write.bytes;
-    _write.bytes = 0;
-    return ret;
-}
-
-void VDIPort::write_completion()
-{
-    DWORD bytes;
-
-    if (!_write.pending) {
-        return;
-    }
-    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;
-}
-
-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)
-{
-    size_t n;
-    size_t m = 0;
-
-    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);
-    } else {
-        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);
-        }
-    }
-    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
-    return n + m;
-}
-
-int VDIPort::read()
-{
-    int size;
-    int ret;
-
-    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();
-        }
-    }
-    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 + bytes) % BUF_SIZE;
-    _read.bytes = bytes;
-    _read.pending = false;
-}
-
-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;
-        return VDI_PORT_RESET;
-    default:
-        vd_printf("port io failed: %u", GetLastError());
-        return VDI_PORT_ERROR;
-    }
-}
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index 8e057bb..2d2b2d2 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -38,27 +38,43 @@ typedef struct 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();
-    unsigned get_num_events() { return 2; }
-    void fill_events(HANDLE *handle) {
+    virtual ~VDIPort() {}
+    virtual bool init() = 0;
+    virtual size_t ring_write(const void* buf, size_t size) = 0;
+    virtual size_t write_ring_free_space() = 0;
+    virtual size_t ring_read(void* buf, size_t size) = 0;
+    virtual size_t read_ring_size() = 0;
+    virtual size_t read_ring_continuous_remaining_size() = 0;
+    virtual unsigned get_num_events() = 0;
+    virtual void fill_events(HANDLE *handle) = 0;
+    virtual void handle_event(int event) = 0;
+    virtual int write() = 0;
+    virtual int read() = 0;
+};
+
+class VirtioVDIPort : public VDIPort {
+public:
+    VirtioVDIPort();
+    ~VirtioVDIPort();
+    virtual bool init();
+    virtual size_t ring_write(const void* buf, size_t size);
+    virtual size_t write_ring_free_space();
+    virtual size_t ring_read(void* buf, size_t size);
+    virtual size_t read_ring_size();
+    virtual size_t read_ring_continuous_remaining_size();
+    virtual unsigned get_num_events() { return 2; }
+    virtual void fill_events(HANDLE *handle) {
         handle[0] = _write.overlap.hEvent;
         handle[1] = _read.overlap.hEvent;
     }
-    void handle_event(int event) {
+    virtual void handle_event(int event) {
         switch (event) {
             case 0: write_completion(); break;
             case 1: read_completion(); break;
         }
     }
-    int write();
-    int read();
+    virtual int write();
+    virtual int read();
 
 private:
     void write_completion();
@@ -66,7 +82,7 @@ private:
     int handle_error();
 
 private:
-    static VDIPort* _singleton;
+    static VirtioVDIPort* _singleton;
     HANDLE _handle;
     VDIPortBuffer _write;
     VDIPortBuffer _read;
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index 72882ea..4c7785b 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -43,7 +43,7 @@
 // This enum simplifies WaitForMultipleEvents for static
 // events, that is handles that are guranteed non NULL.
 // It doesn't include:
-// VDIPort Handles - these are filled by an interface because
+// VirtioVDIPort Handles - these are filled by an interface because
 //  of variable handle number.
 // VDAgent handle - this can be 1 or 0 (NULL or not), so it is also added at
 //  the end of VDService::_events
@@ -434,7 +434,7 @@ bool VDService::execute()
         CloseHandle(pipe);
         return false;
     }
-    _vdi_port = new VDIPort();
+    _vdi_port = new VirtioVDIPort();
     if (!_vdi_port->init()) {
         delete _vdi_port;
         CloseHandle(pipe);
diff --git a/vdservice/virtio_vdi_port.cpp b/vdservice/virtio_vdi_port.cpp
new file mode 100644
index 0000000..8a7cf19
--- /dev/null
+++ b/vdservice/virtio_vdi_port.cpp
@@ -0,0 +1,242 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdio.h"
+#include "vdi_port.h"
+#include "vdlog.h"
+
+#define VIOSERIAL_PORT_PATH                 L"\\\\.\\Global\\com.redhat.spice.0"
+
+// Current limitation of virtio-serial windows driver (RHBZ 617000)
+#define VIOSERIAL_PORT_MAX_WRITE_BYTES      2048
+
+#define MIN(a, b) ((a) > (b) ? (b) : (a))
+
+VirtioVDIPort* VirtioVDIPort::_singleton;
+
+VirtioVDIPort::VirtioVDIPort()
+    : _handle (INVALID_HANDLE_VALUE)
+{
+    ZeroMemory(&_write, offsetof(VDIPortBuffer, ring));
+    _write.start = _write.end = _write.ring;
+    ZeroMemory(&_read, offsetof(VDIPortBuffer, ring));
+    _read.start = _read.end = _read.ring;
+    _singleton = this;
+}
+
+VirtioVDIPort::~VirtioVDIPort()
+{
+    if (_handle != INVALID_HANDLE_VALUE) {
+        CloseHandle(_handle);
+    }
+    if (_read.overlap.hEvent) {
+        CloseHandle(_read.overlap.hEvent);
+    }
+    if (_write.overlap.hEvent) {
+        CloseHandle(_write.overlap.hEvent);
+    }
+}
+
+bool VirtioVDIPort::init()
+{
+    _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
+                         OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+    if (_handle == INVALID_HANDLE_VALUE) {
+        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
+        return false;
+    }
+    _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (_write.overlap.hEvent == NULL) {
+        vd_printf("CreateEvent() failed: %u", GetLastError());
+        return false;
+    }
+    _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 VirtioVDIPort::write_ring_free_space()
+{
+    return (BUF_SIZE + _write.start - _write.end - 1) % BUF_SIZE;
+}
+
+size_t VirtioVDIPort::ring_write(const void* buf, size_t 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);
+    } else {
+        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);
+        }
+    }
+    _write.end = _write.ring + (_write.end - _write.ring + size) % BUF_SIZE;
+    return size;
+}
+
+int VirtioVDIPort::write()
+{
+    int size;
+    int ret;
+
+    //FIXME: return VDI_PORT_NO_DATA
+    if (_write.start == _write.end) {
+        return 0;
+    }
+    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();
+        }
+    }
+    ret = _write.bytes;
+    _write.bytes = 0;
+    return ret;
+}
+
+void VirtioVDIPort::write_completion()
+{
+    DWORD bytes;
+
+    if (!_write.pending) {
+        return;
+    }
+    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 VirtioVDIPort::read_ring_size()
+{
+    return (BUF_SIZE + _read.end - _read.start) % BUF_SIZE;
+}
+
+size_t VirtioVDIPort::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 VirtioVDIPort::ring_read(void* buf, size_t size)
+{
+    size_t n;
+    size_t m = 0;
+
+    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);
+    } else {
+        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);
+        }
+    }
+    _read.start = _read.ring + (_read.start - _read.ring + n + m) % BUF_SIZE;
+    return n + m;
+}
+
+int VirtioVDIPort::read()
+{
+    int size;
+    int ret;
+
+    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();
+        }
+    }
+    ret = _read.bytes;
+    _read.bytes = 0;
+    return ret;
+}
+
+void VirtioVDIPort::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 + bytes) % BUF_SIZE;
+    _read.bytes = bytes;
+    _read.pending = false;
+}
+
+int VirtioVDIPort::handle_error()
+{
+    switch (GetLastError()) {
+    case ERROR_CONNECTION_INVALID:
+        vd_printf("port reset");
+        _write.start = _write.end = _write.ring;
+        _read.start = _read.end = _read.ring;
+        return VDI_PORT_RESET;
+    default:
+        vd_printf("port io failed: %u", GetLastError());
+        return VDI_PORT_ERROR;
+    }
+}
commit 842950d67c12395a8f7bcf28cd551e5207fecf19
Author: Alon Levy <alevy at redhat.com>
Date:   Wed Dec 29 17:27:13 2010 +0200

    start refactoring vdi_port
    
    introduce VDIPort::get_num_events and VDIPort::fill_events,
    change VDService::_events to be dynamically allocated
    document _events contents: STATIC events, then vdi_port, then agent.

diff --git a/vdservice/vdi_port.cpp b/vdservice/vdi_port.cpp
index e36ff86..f4dfaeb 100644
--- a/vdservice/vdi_port.cpp
+++ b/vdservice/vdi_port.cpp
@@ -56,7 +56,7 @@ bool VDIPort::init()
     _handle = CreateFile(VIOSERIAL_PORT_PATH, GENERIC_READ | GENERIC_WRITE , 0, NULL,
                          OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
     if (_handle == INVALID_HANDLE_VALUE) {
-        vd_printf("CreateFile() failed: %u", GetLastError());
+        vd_printf("CreateFile() %s failed: %u", VIOSERIAL_PORT_PATH, GetLastError());
         return false;
     }
     _write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
diff --git a/vdservice/vdi_port.h b/vdservice/vdi_port.h
index a10b346..8e057bb 100644
--- a/vdservice/vdi_port.h
+++ b/vdservice/vdi_port.h
@@ -46,14 +46,23 @@ public:
     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; }
+    unsigned get_num_events() { return 2; }
+    void fill_events(HANDLE *handle) {
+        handle[0] = _write.overlap.hEvent;
+        handle[1] = _read.overlap.hEvent;
+    }
+    void handle_event(int event) {
+        switch (event) {
+            case 0: write_completion(); break;
+            case 1: read_completion(); break;
+        }
+    }
     int write();
     int read();
-    void write_completion();
-    void read_completion();
 
 private:
+    void write_completion();
+    void read_completion();
     int handle_error();
 
 private:
diff --git a/vdservice/vdservice.cpp b/vdservice/vdservice.cpp
index ae5ad87..72882ea 100644
--- a/vdservice/vdservice.cpp
+++ b/vdservice/vdservice.cpp
@@ -40,15 +40,19 @@
 #define CREATE_PROC_MAX_RETRIES 10
 #define CREATE_PROC_INTERVAL_MS 500
 
+// This enum simplifies WaitForMultipleEvents for static
+// events, that is handles that are guranteed non NULL.
+// It doesn't include:
+// VDIPort Handles - these are filled by an interface because
+//  of variable handle number.
+// VDAgent handle - this can be 1 or 0 (NULL or not), so it is also added at
+//  the end of VDService::_events
 enum {
     VD_EVENT_PIPE_READ = 0,
     VD_EVENT_PIPE_WRITE,
     VD_EVENT_CONTROL,
-    VD_EVENT_READ,
-    VD_EVENT_WRITE,
     VD_EVENT_LOGON,
-    VD_EVENT_AGENT, // Must be before last
-    VD_EVENTS_COUNT // Must be last
+    VD_STATIC_EVENTS_COUNT // Must be last
 };
 
 class VDService {
@@ -76,7 +80,15 @@ private:
     bool launch_agent();
     void send_logon();
     bool kill_agent();
-
+    unsigned fill_agent_event() {
+        ASSERT(_events);
+        if (_agent_proc_info.hProcess) {
+            _events[_events_count - 1] = _agent_proc_info.hProcess;
+            return _events_count;
+        } else {
+            return _events_count - 1;
+        }
+    }
 private:
     static VDService* _singleton;
     SERVICE_STATUS _status;
@@ -84,7 +96,7 @@ private:
     PROCESS_INFORMATION _agent_proc_info;
     HANDLE _control_event;
     HANDLE _logon_event;
-    HANDLE _events[VD_EVENTS_COUNT];
+    HANDLE* _events;
     TCHAR _agent_path[MAX_PATH];
     VDIPort* _vdi_port;
     VDPipeState _pipe_state;
@@ -103,6 +115,8 @@ private:
     bool _agent_alive;
     bool _running;
     VDLog* _log;
+    unsigned _events_count;
+    unsigned _events_vdi_port_base;
 };
 
 VDService* VDService::_singleton = NULL;
@@ -142,6 +156,7 @@ int supported_system_version()
 
 VDService::VDService()
     : _status_handle (0)
+    , _events (NULL)
     , _vdi_port (NULL)
     , _connection_id (0)
     , _session_id (0)
@@ -156,10 +171,11 @@ VDService::VDService()
     , _agent_alive (false)
     , _running (false)
     , _log (NULL)
+    , _events_count(0)
+    , _events_vdi_port_base(0)
 {
     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.write.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -176,6 +192,7 @@ VDService::~VDService()
     CloseHandle(_pipe_state.read.overlap.hEvent);
     CloseHandle(_pipe_state.write.overlap.hEvent);
     CloseHandle(_control_event);
+    delete _events;
     delete _log;
 }
 
@@ -423,14 +440,19 @@ bool VDService::execute()
         CloseHandle(pipe);
         return false;
     }
+    _events_count = VD_STATIC_EVENTS_COUNT + _vdi_port->get_num_events() + 1 /*for agent*/;
+    _events = new HANDLE[_events_count];
+    _events_vdi_port_base = VD_STATIC_EVENTS_COUNT;
+    ZeroMemory(_events, _events_count);
     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();
     _events[VD_EVENT_LOGON] = _logon_event;
-    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
+    _agent_proc_info.hProcess;
+    vd_printf("Calling fill_events");
+    vd_printf("&_events[VD_ENVETS_COUNT] == %p", &_events[VD_STATIC_EVENTS_COUNT]);
+    _vdi_port->fill_events(&_events[_events_vdi_port_base]);
     _chunk_size = _chunk_port = 0;
     read_pipe();
     while (_running) {
@@ -456,8 +478,8 @@ bool VDService::execute()
             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 = WaitForMultipleObjects(events_count, _events, FALSE,
+            unsigned actual_events = fill_agent_event();
+            DWORD wait_ret = WaitForMultipleObjects(actual_events, _events, FALSE,
                                                               cont ? 0 : INFINITE);
             switch (wait_ret) {
             case WAIT_OBJECT_0 + VD_EVENT_PIPE_READ: {
@@ -482,28 +504,29 @@ bool VDService::execute()
             case WAIT_OBJECT_0 + VD_EVENT_CONTROL:
                 vd_printf("Control event");
                 break;
-            case WAIT_OBJECT_0 + VD_EVENT_READ:
-                _vdi_port->read_completion();
-                break;
-            case WAIT_OBJECT_0 + VD_EVENT_WRITE:
-                _vdi_port->write_completion();
-                break;
             case WAIT_OBJECT_0 + VD_EVENT_LOGON:
                 vd_printf("logon event");
                 write_agent_control(VD_AGENT_SESSION_LOGON, 0);
                 break;
-            case WAIT_OBJECT_0 + VD_EVENT_AGENT:
-                vd_printf("Agent killed");
-                if (_system_version == SYS_VER_WIN_XP) {
-                    restart_agent(false);
-                } else if (_system_version == SYS_VER_WIN_7) {
-                    kill_agent();
-                }
-                break;
             case WAIT_TIMEOUT:
                 break;
             default:
-                vd_printf("WaitForMultipleObjects failed %u", GetLastError());
+                if (wait_ret == WAIT_OBJECT_0 + _events_count - 1) {
+                    vd_printf("Agent killed");
+                    if (_system_version == SYS_VER_WIN_XP) {
+                        restart_agent(false);
+                    } else if (_system_version == SYS_VER_WIN_7) {
+                        kill_agent();
+                    }
+                } else {
+                    if (wait_ret >= WAIT_OBJECT_0 + _events_vdi_port_base &&
+                        wait_ret < WAIT_OBJECT_0 +
+                                   _events_vdi_port_base + _vdi_port->get_num_events()) {
+                        _vdi_port->handle_event(wait_ret - VD_STATIC_EVENTS_COUNT - WAIT_OBJECT_0);
+                    } else {
+                        vd_printf("WaitForMultipleObjects failed %u", GetLastError());
+                    }
+                }
             }
         }
     }
@@ -802,7 +825,6 @@ bool VDService::launch_agent()
         vd_printf("ConnectNamedPipe() failed: %u", GetLastError());
         return false;
     }
-    _events[VD_EVENT_AGENT] = _agent_proc_info.hProcess;
     return true;
 }
 
@@ -815,7 +837,6 @@ bool VDService::kill_agent()
     if (!_agent_alive) {
         return true;
     }
-    _events[VD_EVENT_AGENT] = 0;
     _agent_alive = false;
     if (_pipe_connected) {
         _pipe_connected = false;
@@ -909,8 +930,8 @@ void VDService::pipe_write_completion()
         } else {
             vd_printf("GetOverlappedResult() failed : %d", GetLastError());
         }
-	    _pending_write = false;
-	}
+        _pending_write = false;
+    }
 
     if (ps->write.start < ps->write.end) {
         _pending_write = true;


More information about the Spice-commits mailing list