[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 16/66] vbox: Rewrite vboxDomainDefineXML



---
 src/vbox/vbox_common.c        | 1169 +++++++++++
 src/vbox/vbox_common.h        |   90 +
 src/vbox/vbox_tmpl.c          | 4535 ++++++++++++++++++++---------------------
 src/vbox/vbox_uniformed_api.h |  128 ++
 4 files changed, 3557 insertions(+), 2365 deletions(-)

diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index efcda7a..f4e992d 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -81,6 +81,14 @@ VIR_LOG_INIT("vbox.vbox_common");
         }                                                                     \
     } while (0)
 
+#define VBOX_MEDIUM_RELEASE(arg)                                              \
+    do {                                                                      \
+        if (arg) {                                                            \
+            gVBoxAPI.UIMedium.Release(arg);                                   \
+            (arg) = NULL;                                                     \
+        }                                                                     \
+    } while (0)
+
 #define VBOX_OBJECT_CHECK(conn, type, value) \
 vboxGlobalData *data = conn->privateData;\
 type ret = value;\
@@ -152,6 +160,123 @@ static int openSessionForMachine(vboxGlobalData *data, const unsigned char *dom_
     return 0;
 }
 
+/**
+ * function to get the values for max port per
+ * instance and max slots per port for the devices
+ *
+ * @returns     true on Success, false on failure.
+ * @param       vbox            Input IVirtualBox pointer
+ * @param       maxPortPerInst  Output array of max port per instance
+ * @param       maxSlotPerPort  Output array of max slot per port
+ *
+ */
+
+static bool vboxGetMaxPortSlotValues(IVirtualBox *vbox,
+                                     PRUint32 *maxPortPerInst,
+                                     PRUint32 *maxSlotPerPort)
+{
+    ISystemProperties *sysProps = NULL;
+
+    if (!vbox)
+        return false;
+
+    gVBoxAPI.UIVirtualBox.GetSystemProperties(vbox, &sysProps);
+
+    if (!sysProps)
+        return false;
+
+    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
+                                                             StorageBus_IDE,
+                                                             &maxPortPerInst[StorageBus_IDE]);
+    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
+                                                             StorageBus_SATA,
+                                                             &maxPortPerInst[StorageBus_SATA]);
+    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
+                                                             StorageBus_SCSI,
+                                                             &maxPortPerInst[StorageBus_SCSI]);
+    gVBoxAPI.UISystemProperties.GetMaxPortCountForStorageBus(sysProps,
+                                                             StorageBus_Floppy,
+                                                             &maxPortPerInst[StorageBus_Floppy]);
+
+    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
+                                                                  StorageBus_IDE,
+                                                                  &maxSlotPerPort[StorageBus_IDE]);
+    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
+                                                                  StorageBus_SATA,
+                                                                  &maxSlotPerPort[StorageBus_SATA]);
+    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
+                                                                  StorageBus_SCSI,
+                                                                  &maxSlotPerPort[StorageBus_SCSI]);
+    gVBoxAPI.UISystemProperties.GetMaxDevicesPerPortForStorageBus(sysProps,
+                                                                  StorageBus_Floppy,
+                                                                  &maxSlotPerPort[StorageBus_Floppy]);
+
+    VBOX_RELEASE(sysProps);
+
+    return true;
+}
+
+/**
+ * function to get the StorageBus, Port number
+ * and Device number for the given devicename
+ * e.g: hda has StorageBus = IDE, port = 0,
+ *      device = 0
+ *
+ * @returns     true on Success, false on failure.
+ * @param       deviceName      Input device name
+ * @param       aMaxPortPerInst Input array of max port per device instance
+ * @param       aMaxSlotPerPort Input array of max slot per device port
+ * @param       storageBus      Input storage bus type
+ * @param       deviceInst      Output device instance number
+ * @param       devicePort      Output port number
+ * @param       deviceSlot      Output slot number
+ *
+ */
+static bool vboxGetDeviceDetails(const char *deviceName,
+                                 PRUint32   *aMaxPortPerInst,
+                                 PRUint32   *aMaxSlotPerPort,
+                                 PRUint32    storageBus,
+                                 PRInt32    *deviceInst,
+                                 PRInt32    *devicePort,
+                                 PRInt32    *deviceSlot) {
+    int total = 0;
+    PRUint32 maxPortPerInst = 0;
+    PRUint32 maxSlotPerPort = 0;
+
+    if (!deviceName ||
+        !deviceInst ||
+        !devicePort ||
+        !deviceSlot ||
+        !aMaxPortPerInst ||
+        !aMaxSlotPerPort)
+        return false;
+
+    if ((storageBus < StorageBus_IDE) ||
+        (storageBus > StorageBus_Floppy))
+        return false;
+
+    total = virDiskNameToIndex(deviceName);
+
+    maxPortPerInst = aMaxPortPerInst[storageBus];
+    maxSlotPerPort = aMaxSlotPerPort[storageBus];
+
+    if (!maxPortPerInst ||
+        !maxSlotPerPort ||
+        (total < 0))
+        return false;
+
+    *deviceInst = total / (maxPortPerInst * maxSlotPerPort);
+    *devicePort = (total % (maxPortPerInst * maxSlotPerPort)) / maxSlotPerPort;
+    *deviceSlot = (total % (maxPortPerInst * maxSlotPerPort)) % maxSlotPerPort;
+
+    VIR_DEBUG("name=%s, total=%d, storageBus=%u, deviceInst=%d, "
+          "devicePort=%d deviceSlot=%d, maxPortPerInst=%u maxSlotPerPort=%u",
+          deviceName, total, storageBus, *deviceInst, *devicePort,
+          *deviceSlot, maxPortPerInst, maxSlotPerPort);
+
+    return true;
+}
+
 static virDomainDefParserConfig vboxDomainDefParserConfig = {
     .macPrefix = { 0x08, 0x00, 0x27 },
 };
@@ -700,6 +825,1050 @@ virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn,
 }
 
 static void
+vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data,
+                       IMachine *machine)
+{
+    ISystemProperties *systemProperties = NULL;
+    PRUint32 maxBootPosition            = 0;
+    size_t i = 0;
+
+    VIR_DEBUG("def->os.type             %s", def->os.type);
+    VIR_DEBUG("def->os.arch             %s", virArchToString(def->os.arch));
+    VIR_DEBUG("def->os.machine          %s", def->os.machine);
+    VIR_DEBUG("def->os.nBootDevs        %zu", def->os.nBootDevs);
+    VIR_DEBUG("def->os.bootDevs[0]      %d", def->os.bootDevs[0]);
+    VIR_DEBUG("def->os.bootDevs[1]      %d", def->os.bootDevs[1]);
+    VIR_DEBUG("def->os.bootDevs[2]      %d", def->os.bootDevs[2]);
+    VIR_DEBUG("def->os.bootDevs[3]      %d", def->os.bootDevs[3]);
+    VIR_DEBUG("def->os.init             %s", def->os.init);
+    VIR_DEBUG("def->os.kernel           %s", def->os.kernel);
+    VIR_DEBUG("def->os.initrd           %s", def->os.initrd);
+    VIR_DEBUG("def->os.cmdline          %s", def->os.cmdline);
+    VIR_DEBUG("def->os.root             %s", def->os.root);
+    VIR_DEBUG("def->os.loader           %s", def->os.loader);
+    VIR_DEBUG("def->os.bootloader       %s", def->os.bootloader);
+    VIR_DEBUG("def->os.bootloaderArgs   %s", def->os.bootloaderArgs);
+
+    gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties);
+    if (systemProperties) {
+        gVBoxAPI.UISystemProperties.GetMaxBootPosition(systemProperties,
+                                                       &maxBootPosition);
+        VBOX_RELEASE(systemProperties);
+    }
+
+    /* Clear the defaults first */
+    for (i = 0; i < maxBootPosition; i++) {
+        gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, DeviceType_Null);
+    }
+
+    for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) {
+        PRUint32 device = DeviceType_Null;
+
+        if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) {
+            device = DeviceType_Floppy;
+        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) {
+            device = DeviceType_DVD;
+        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) {
+            device = DeviceType_HardDisk;
+        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
+            device = DeviceType_Network;
+        }
+        gVBoxAPI.UIMachine.SetBootOrder(machine, i+1, device);
+    }
+}
+
+static void
+vboxAttachDrivesNew(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    /* AttachDrives for 3.0 and later */
+    size_t i;
+    nsresult rc;
+    PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
+    PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
+    PRUnichar *storageCtlName = NULL;
+    bool error = false;
+
+    if (gVBoxAPI.vboxAttachDrivesUseOld)
+        VIR_WARN("This function may not work in current vbox version");
+
+    /* get the max port/slots/etc for the given storage bus */
+    error = !vboxGetMaxPortSlotValues(data->vboxObj, maxPortPerInst,
+                                      maxSlotPerPort);
+
+    /* add a storage controller for the mediums to be attached */
+    /* this needs to change when multiple controller are supported for
+     * ver > 3.1 */
+    {
+        IStorageController *storageCtl = NULL;
+        PRUnichar *sName = NULL;
+
+        VBOX_UTF8_TO_UTF16("IDE Controller", &sName);
+        gVBoxAPI.UIMachine.AddStorageController(machine,
+                                                sName,
+                                                StorageBus_IDE,
+                                                &storageCtl);
+        VBOX_UTF16_FREE(sName);
+        VBOX_RELEASE(storageCtl);
+
+        VBOX_UTF8_TO_UTF16("SATA Controller", &sName);
+        gVBoxAPI.UIMachine.AddStorageController(machine,
+                                                sName,
+                                                StorageBus_SATA,
+                                                &storageCtl);
+        VBOX_UTF16_FREE(sName);
+        VBOX_RELEASE(storageCtl);
+
+        VBOX_UTF8_TO_UTF16("SCSI Controller", &sName);
+        gVBoxAPI.UIMachine.AddStorageController(machine,
+                                                sName,
+                                                StorageBus_SCSI,
+                                                &storageCtl);
+        VBOX_UTF16_FREE(sName);
+        VBOX_RELEASE(storageCtl);
+
+        VBOX_UTF8_TO_UTF16("Floppy Controller", &sName);
+        gVBoxAPI.UIMachine.AddStorageController(machine,
+                                                sName,
+                                                StorageBus_Floppy,
+                                                &storageCtl);
+        VBOX_UTF16_FREE(sName);
+        VBOX_RELEASE(storageCtl);
+    }
+
+    for (i = 0; i < def->ndisks && !error; i++) {
+        const char *src = virDomainDiskGetSource(def->disks[i]);
+        int type = virDomainDiskGetType(def->disks[i]);
+        int format = virDomainDiskGetFormat(def->disks[i]);
+
+        VIR_DEBUG("disk(%zu) type:       %d", i, type);
+        VIR_DEBUG("disk(%zu) device:     %d", i, def->disks[i]->device);
+        VIR_DEBUG("disk(%zu) bus:        %d", i, def->disks[i]->bus);
+        VIR_DEBUG("disk(%zu) src:        %s", i, src);
+        VIR_DEBUG("disk(%zu) dst:        %s", i, def->disks[i]->dst);
+        VIR_DEBUG("disk(%zu) driverName: %s", i,
+                  virDomainDiskGetDriver(def->disks[i]));
+        VIR_DEBUG("disk(%zu) driverType: %s", i,
+                  virStorageFileFormatTypeToString(format));
+        VIR_DEBUG("disk(%zu) cachemode:  %d", i, def->disks[i]->cachemode);
+        VIR_DEBUG("disk(%zu) readonly:   %s", i, (def->disks[i]->src->readonly
+                                             ? "True" : "False"));
+        VIR_DEBUG("disk(%zu) shared:     %s", i, (def->disks[i]->src->shared
+                                             ? "True" : "False"));
+
+        if (type == VIR_STORAGE_TYPE_FILE && src) {
+            IMedium   *medium          = NULL;
+            vboxIIDUnion mediumUUID;
+            PRUnichar *mediumFileUtf16 = NULL;
+            PRUint32   storageBus      = StorageBus_Null;
+            PRUint32   deviceType      = DeviceType_Null;
+            PRUint32   accessMode      = AccessMode_ReadOnly;
+            PRInt32    deviceInst      = 0;
+            PRInt32    devicePort      = 0;
+            PRInt32    deviceSlot      = 0;
+
+            VBOX_IID_INITIALIZE(&mediumUUID);
+            VBOX_UTF8_TO_UTF16(src, &mediumFileUtf16);
+
+            if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+                deviceType = DeviceType_HardDisk;
+                accessMode = AccessMode_ReadWrite;
+            } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+                deviceType = DeviceType_DVD;
+                accessMode = AccessMode_ReadOnly;
+            } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+                deviceType = DeviceType_Floppy;
+                accessMode = AccessMode_ReadWrite;
+            } else {
+                VBOX_UTF16_FREE(mediumFileUtf16);
+                continue;
+            }
+
+            gVBoxAPI.UIVirtualBox.FindMedium(data->vboxObj, mediumFileUtf16,
+                                             deviceType, accessMode, &medium);
+
+            if (!medium) {
+                PRUnichar *mediumEmpty = NULL;
+
+                VBOX_UTF8_TO_UTF16("", &mediumEmpty);
+
+                rc = gVBoxAPI.UIVirtualBox.OpenMedium(data->vboxObj,
+                                                      mediumFileUtf16,
+                                                      deviceType, accessMode,
+                                                      &medium);
+                VBOX_UTF16_FREE(mediumEmpty);
+            }
+
+            if (!medium) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Failed to attach the following disk/dvd/floppy "
+                                 "to the machine: %s, rc=%08x"),
+                               src, (unsigned)rc);
+                VBOX_UTF16_FREE(mediumFileUtf16);
+                continue;
+            }
+
+            rc = gVBoxAPI.UIMedium.GetId(medium, &mediumUUID);
+            if (NS_FAILED(rc)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("can't get the uuid of the file to be attached "
+                                 "as harddisk/dvd/floppy: %s, rc=%08x"),
+                               src, (unsigned)rc);
+                VBOX_MEDIUM_RELEASE(medium);
+                VBOX_UTF16_FREE(mediumFileUtf16);
+                continue;
+            }
+
+            if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
+                if (def->disks[i]->src->readonly) {
+                    gVBoxAPI.UIMedium.SetType(medium, MediumType_Immutable);
+                    VIR_DEBUG("setting harddisk to immutable");
+                } else if (!def->disks[i]->src->readonly) {
+                    gVBoxAPI.UIMedium.SetType(medium, MediumType_Normal);
+                    VIR_DEBUG("setting harddisk type to normal");
+                }
+            }
+
+            if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_IDE) {
+                VBOX_UTF8_TO_UTF16("IDE Controller", &storageCtlName);
+                storageBus = StorageBus_IDE;
+            } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SATA) {
+                VBOX_UTF8_TO_UTF16("SATA Controller", &storageCtlName);
+                storageBus = StorageBus_SATA;
+            } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
+                VBOX_UTF8_TO_UTF16("SCSI Controller", &storageCtlName);
+                storageBus = StorageBus_SCSI;
+            } else if (def->disks[i]->bus == VIR_DOMAIN_DISK_BUS_FDC) {
+                VBOX_UTF8_TO_UTF16("Floppy Controller", &storageCtlName);
+                storageBus = StorageBus_Floppy;
+            }
+
+            /* get the device details i.e instance, port and slot */
+            if (!vboxGetDeviceDetails(def->disks[i]->dst,
+                                      maxPortPerInst,
+                                      maxSlotPerPort,
+                                      storageBus,
+                                      &deviceInst,
+                                      &devicePort,
+                                      &deviceSlot)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("can't get the port/slot number of "
+                                 "harddisk/dvd/floppy to be attached: "
+                                 "%s, rc=%08x"),
+                               src, (unsigned)rc);
+                VBOX_MEDIUM_RELEASE(medium);
+                vboxIIDUnalloc(&mediumUUID);
+                VBOX_UTF16_FREE(mediumFileUtf16);
+                continue;
+            }
+
+            /* attach the harddisk/dvd/Floppy to the storage controller */
+            rc = gVBoxAPI.UIMachine.AttachDevice(machine,
+                                                 storageCtlName,
+                                                 devicePort,
+                                                 deviceSlot,
+                                                 deviceType,
+                                                 medium);
+
+            if (NS_FAILED(rc)) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("could not attach the file as "
+                                 "harddisk/dvd/floppy: %s, rc=%08x"),
+                               src, (unsigned)rc);
+            } else {
+                DEBUGIID("Attached HDD/DVD/Floppy with UUID", &mediumUUID);
+            }
+
+            VBOX_MEDIUM_RELEASE(medium);
+            vboxIIDUnalloc(&mediumUUID);
+            VBOX_UTF16_FREE(mediumFileUtf16);
+            VBOX_UTF16_FREE(storageCtlName);
+        }
+    }
+}
+
+static void
+vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    /* Here, About the vboxAttachDrives. In fact,there is
+     * three different implementations. We name it as
+     * v1, v2 and v3.
+     *
+     * The first version(v1) is only used in vbox 2.2 and 3.0,
+     * v2 is used by 3.1 and 3.2, and v3 is used for later
+     * vbox versions. In sight of implementation, the v1 is
+     * totally different with v2 and v3. The v2 shares the same
+     * outline with v3, meanwhile the API they used has much
+     * difference.
+     *
+     * It seems we have no thing to do with old versions such as
+     * v1 and v2 when developing new vbox drivers. What's more,
+     * most of the vbox APIs used in v1 and v2 is incompatible with
+     * new vbox versions. It is a burden to put these APIs into
+     * vboxUniformedAPI, I prefer not to do that.
+     *
+     * After balancing the code size and the complied code size,
+     * I put my solution here. The v1 and v2 is a version specified
+     * code, which only be generated for first four version. The v3
+     * will be put in vbox_common.c, it be complied only once, then
+     * be used by all next vbox drivers.
+     *
+     * Check the flag vboxAttachDrivesUseOld can tell you which
+     * implementation to use. When the flag is set, we need use
+     * the old version though gVBoxAPI.vboxAttachDrivesOld. It
+     * will automatically point to v1 or v2 deponds on you version.
+     * If the flag is clear, just call vboxAttachDrivesNew, which
+     * is the v3 implementation.
+     */
+    if (gVBoxAPI.vboxAttachDrivesUseOld)
+        gVBoxAPI.vboxAttachDrivesOld(def, data, machine);
+    else
+        vboxAttachDrivesNew(def, data, machine);
+}
+
+static void
+vboxAttachSound(virDomainDefPtr def, IMachine *machine)
+{
+    nsresult rc;
+    IAudioAdapter *audioAdapter = NULL;
+
+    /* Check if def->nsounds is one as VirtualBox currently supports
+     * only one sound card
+     */
+    if (def->nsounds != 1)
+        return;
+
+    gVBoxAPI.UIMachine.GetAudioAdapter(machine, &audioAdapter);
+    if (!audioAdapter)
+        return;
+
+    rc = gVBoxAPI.UIAudioAdapter.SetEnabled(audioAdapter, 1);
+    if (NS_FAILED(rc))
+        goto cleanup;
+
+    if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) {
+        gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter,
+                                                   AudioControllerType_SB16);
+    } else
+    if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) {
+        gVBoxAPI.UIAudioAdapter.SetAudioController(audioAdapter,
+                                                   AudioControllerType_AC97);
+    }
+
+ cleanup:
+    VBOX_RELEASE(audioAdapter);
+}
+
+static void
+vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    ISystemProperties *systemProperties = NULL;
+    PRUint32 chipsetType                = ChipsetType_Null;
+    PRUint32 networkAdapterCount        = 0;
+    size_t i = 0;
+
+    if (gVBoxAPI.chipsetType)
+        gVBoxAPI.UIMachine.GetChipsetType(machine, &chipsetType);
+
+    gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties);
+    if (systemProperties) {
+        gVBoxAPI.UISystemProperties.GetMaxNetworkAdapters(systemProperties, chipsetType,
+                                                          &networkAdapterCount);
+        VBOX_RELEASE(systemProperties);
+    }
+
+    VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets);
+    VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount);
+
+    for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) {
+        INetworkAdapter *adapter = NULL;
+        PRUint32 adapterType     = NetworkAdapterType_Null;
+        char macaddr[VIR_MAC_STRING_BUFLEN] = {0};
+        char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0};
+        PRUnichar *MACAddress = NULL;
+
+        virMacAddrFormat(&def->nets[i]->mac, macaddr);
+        snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5,
+                 "%02X%02X%02X%02X%02X%02X",
+                 def->nets[i]->mac.addr[0],
+                 def->nets[i]->mac.addr[1],
+                 def->nets[i]->mac.addr[2],
+                 def->nets[i]->mac.addr[3],
+                 def->nets[i]->mac.addr[4],
+                 def->nets[i]->mac.addr[5]);
+        macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0';
+
+        VIR_DEBUG("NIC(%zu): Type:   %d", i, def->nets[i]->type);
+        VIR_DEBUG("NIC(%zu): Model:  %s", i, def->nets[i]->model);
+        VIR_DEBUG("NIC(%zu): Mac:    %s", i, macaddr);
+        VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname);
+        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+            VIR_DEBUG("NIC(%zu): name:    %s", i, def->nets[i]->data.network.name);
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
+            VIR_DEBUG("NIC(%zu): name:   %s", i, def->nets[i]->data.internal.name);
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
+            VIR_DEBUG("NIC(%zu): NAT.", i);
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+            VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname);
+            VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script);
+            VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr);
+        }
+
+        gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter);
+        if (!adapter)
+            continue;
+
+        gVBoxAPI.UINetworkAdapter.SetEnabled(adapter, 1);
+
+        if (def->nets[i]->model) {
+            if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) {
+                adapterType = NetworkAdapterType_Am79C970A;
+            } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) {
+                adapterType = NetworkAdapterType_Am79C973;
+            } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) {
+                adapterType = NetworkAdapterType_I82540EM;
+            } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) {
+                adapterType = NetworkAdapterType_I82545EM;
+            } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) {
+                adapterType = NetworkAdapterType_I82543GC;
+            } else if (gVBoxAPI.APIVersion >= 3000051 &&
+                       STRCASEEQ(def->nets[i]->model, "virtio")) {
+                /* Only vbox 3.1 and later support NetworkAdapterType_Virto */
+                adapterType = NetworkAdapterType_Virtio;
+            }
+        } else {
+            adapterType = NetworkAdapterType_Am79C973;
+        }
+
+        gVBoxAPI.UINetworkAdapter.SetAdapterType(adapter, adapterType);
+
+        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+            PRUnichar *hostInterface = NULL;
+            /* Bridged Network */
+
+            gVBoxAPI.UINetworkAdapter.AttachToBridgedInterface(adapter);
+
+            if (def->nets[i]->data.bridge.brname) {
+                VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname,
+                                   &hostInterface);
+                gVBoxAPI.UINetworkAdapter.SetBridgedInterface(adapter, hostInterface);
+                VBOX_UTF16_FREE(hostInterface);
+            }
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
+            PRUnichar *internalNetwork = NULL;
+            /* Internal Network */
+
+            gVBoxAPI.UINetworkAdapter.AttachToInternalNetwork(adapter);
+
+            if (def->nets[i]->data.internal.name) {
+                VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name,
+                                   &internalNetwork);
+                gVBoxAPI.UINetworkAdapter.SetInternalNetwork(adapter, internalNetwork);
+                VBOX_UTF16_FREE(internalNetwork);
+            }
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+            PRUnichar *hostInterface = NULL;
+            /* Host Only Networking (currently only vboxnet0 available
+             * on *nix and mac, on windows you can create and configure
+             * as many as you want)
+             */
+            gVBoxAPI.UINetworkAdapter.AttachToHostOnlyInterface(adapter);
+
+            if (def->nets[i]->data.network.name) {
+                VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name,
+                                   &hostInterface);
+                gVBoxAPI.UINetworkAdapter.SetHostOnlyInterface(adapter, hostInterface);
+                VBOX_UTF16_FREE(hostInterface);
+            }
+        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
+            /* NAT */
+            gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter);
+        } else {
+            /* else always default to NAT if we don't understand
+             * what option is been passed to us
+             */
+            gVBoxAPI.UINetworkAdapter.AttachToNAT(adapter);
+        }
+
+        VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress);
+        gVBoxAPI.UINetworkAdapter.SetMACAddress(adapter, MACAddress);
+        VBOX_UTF16_FREE(MACAddress);
+    }
+}
+
+static void
+vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    ISystemProperties *systemProperties = NULL;
+    PRUint32 serialPortCount            = 0;
+    size_t i = 0;
+
+    gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties);
+    if (systemProperties) {
+        gVBoxAPI.UISystemProperties.GetSerialPortCount(systemProperties,
+                                                       &serialPortCount);
+        VBOX_RELEASE(systemProperties);
+    }
+
+    VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials);
+    VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount);
+
+    for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) {
+        ISerialPort *serialPort = NULL;
+        PRUnichar *pathUtf16 = NULL;
+
+        VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type);
+        VIR_DEBUG("SerialPort(%zu): target.port: %d", i,
+              def->serials[i]->target.port);
+
+        gVBoxAPI.UIMachine.GetSerialPort(machine, i, &serialPort);
+        if (!serialPort)
+            continue;
+
+        gVBoxAPI.UISerialPort.SetEnabled(serialPort, 1);
+
+        if (def->serials[i]->source.data.file.path) {
+            VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path,
+                               &pathUtf16);
+            gVBoxAPI.UISerialPort.SetPath(serialPort, pathUtf16);
+        }
+
+        /* For now hard code the serial ports to COM1 and COM2,
+         * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4)
+         * COM2 (Base Addr: 0x2F8 (decimal:  760), IRQ: 3)
+         * TODO: make this more flexible
+         */
+        /* TODO: to improve the libvirt XMl handling so
+         * that def->serials[i]->target.port shows real port
+         * and not always start at 0
+         */
+        if (def->serials[i]->target.port == 0) {
+            gVBoxAPI.UISerialPort.SetIRQ(serialPort, 4);
+            gVBoxAPI.UISerialPort.SetIOBase(serialPort, 1016);
+            VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
+                  i, 4, 1016, def->serials[i]->source.data.file.path);
+        } else if (def->serials[i]->target.port == 1) {
+            gVBoxAPI.UISerialPort.SetIRQ(serialPort, 3);
+            gVBoxAPI.UISerialPort.SetIOBase(serialPort, 760);
+            VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
+                  i, 3, 760, def->serials[i]->source.data.file.path);
+        }
+
+        if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) {
+            gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostDevice);
+        } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) {
+            gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_HostPipe);
+        } else if (gVBoxAPI.APIVersion >= 2002051 &&
+                   def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) {
+            /* PortMode RawFile is used for vbox 3.0 or later */
+            gVBoxAPI.UISerialPort.SetHostMode(serialPort, PortMode_RawFile);
+        } else {
+            gVBoxAPI.UISerialPort.SetHostMode(serialPort,
+                                              PortMode_Disconnected);
+        }
+
+        VBOX_RELEASE(serialPort);
+        VBOX_UTF16_FREE(pathUtf16);
+    }
+}
+
+static void
+vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    ISystemProperties *systemProperties = NULL;
+    PRUint32 parallelPortCount          = 0;
+    size_t i = 0;
+
+    gVBoxAPI.UIVirtualBox.GetSystemProperties(data->vboxObj, &systemProperties);
+    if (systemProperties) {
+        gVBoxAPI.UISystemProperties.GetParallelPortCount(systemProperties,
+                                                         &parallelPortCount);
+        VBOX_RELEASE(systemProperties);
+    }
+
+    VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels);
+    VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount);
+    for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) {
+        IParallelPort *parallelPort = NULL;
+        PRUnichar *pathUtf16 = NULL;
+
+        VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type);
+        VIR_DEBUG("ParallelPort(%zu): target.port: %d", i,
+              def->parallels[i]->target.port);
+
+        gVBoxAPI.UIMachine.GetParallelPort(machine, i, &parallelPort);
+        if (!parallelPort)
+            continue;
+
+        VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16);
+
+        /* For now hard code the parallel ports to
+         * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7)
+         * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5)
+         * TODO: make this more flexible
+         */
+        if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV)  ||
+            (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY)  ||
+            (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) ||
+            (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) {
+            gVBoxAPI.UIParallelPort.SetPath(parallelPort, pathUtf16);
+            if (i == 0) {
+                gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 7);
+                gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 888);
+                VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
+                      i, 7, 888, def->parallels[i]->source.data.file.path);
+            } else if (i == 1) {
+                gVBoxAPI.UIParallelPort.SetIRQ(parallelPort, 5);
+                gVBoxAPI.UIParallelPort.SetIOBase(parallelPort, 632);
+                VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
+                      i, 5, 632, def->parallels[i]->source.data.file.path);
+            }
+        }
+
+        /* like serial port, parallel port can't be enabled unless
+         * correct IRQ and IOBase values are specified.
+         */
+        gVBoxAPI.UIParallelPort.SetEnabled(parallelPort, 1);
+
+        VBOX_RELEASE(parallelPort);
+        VBOX_UTF16_FREE(pathUtf16);
+    }
+}
+
+static void
+vboxAttachVideo(virDomainDefPtr def, IMachine *machine)
+{
+    if ((def->nvideos == 1) &&
+        (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) {
+        gVBoxAPI.UIMachine.SetVRAMSize(machine,
+                                       VIR_DIV_UP(def->videos[0]->vram, 1024));
+        gVBoxAPI.UIMachine.SetMonitorCount(machine, def->videos[0]->heads);
+        if (def->videos[0]->accel) {
+            gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine,
+                                                      def->videos[0]->accel->support3d);
+            if (gVBoxAPI.accelerate2DVideo)
+                gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine,
+                                                               def->videos[0]->accel->support2d);
+        } else {
+            gVBoxAPI.UIMachine.SetAccelerate3DEnabled(machine, 0);
+            if (gVBoxAPI.accelerate2DVideo)
+                gVBoxAPI.UIMachine.SetAccelerate2DVideoEnabled(machine, 0);
+        }
+    }
+}
+
+static void
+vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    int vrdpPresent  = 0;
+    int sdlPresent   = 0;
+    int guiPresent   = 0;
+    char *guiDisplay = NULL;
+    char *sdlDisplay = NULL;
+    size_t i = 0;
+
+    for (i = 0; i < def->ngraphics; i++) {
+        IVRDxServer *VRDxServer = NULL;
+
+        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) &&
+            (vrdpPresent == 0)) {
+
+            vrdpPresent = 1;
+            gVBoxAPI.UIMachine.GetVRDxServer(machine, &VRDxServer);
+            if (VRDxServer) {
+                const char *listenAddr
+                    = virDomainGraphicsListenGetAddress(def->graphics[i], 0);
+
+                gVBoxAPI.UIVRDxServer.SetEnabled(VRDxServer, PR_TRUE);
+                VIR_DEBUG("VRDP Support turned ON.");
+
+                gVBoxAPI.UIVRDxServer.SetPorts(data, VRDxServer, def->graphics[i]);
+
+                if (def->graphics[i]->data.rdp.replaceUser) {
+                    gVBoxAPI.UIVRDxServer.SetReuseSingleConnection(VRDxServer,
+                                                                   PR_TRUE);
+                    VIR_DEBUG("VRDP set to reuse single connection");
+                }
+
+                if (def->graphics[i]->data.rdp.multiUser) {
+                    gVBoxAPI.UIVRDxServer.SetAllowMultiConnection(VRDxServer,
+                                                                  PR_TRUE);
+                    VIR_DEBUG("VRDP set to allow multiple connection");
+                }
+
+                if (listenAddr) {
+                    PRUnichar *netAddressUtf16 = NULL;
+
+                    VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16);
+                    gVBoxAPI.UIVRDxServer.SetNetAddress(data, VRDxServer,
+                                                        netAddressUtf16);
+                    VIR_DEBUG("VRDP listen address is set to: %s",
+                              listenAddr);
+
+                    VBOX_UTF16_FREE(netAddressUtf16);
+                }
+
+                VBOX_RELEASE(VRDxServer);
+            }
+        }
+
+        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) &&
+            (guiPresent == 0)) {
+            guiPresent = 1;
+            if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) {
+                /* just don't go to cleanup yet as it is ok to have
+                 * guiDisplay as NULL and we check it below if it
+                 * exist and then only use it there
+                 */
+            }
+        }
+
+        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) &&
+            (sdlPresent == 0)) {
+            sdlPresent = 1;
+            if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) {
+                /* just don't go to cleanup yet as it is ok to have
+                 * sdlDisplay as NULL and we check it below if it
+                 * exist and then only use it there
+                 */
+            }
+        }
+    }
+
+    if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) {
+        /* store extradata key that frontend is set to vrdp */
+        PRUnichar *keyTypeUtf16   = NULL;
+        PRUnichar *valueTypeUtf16 = NULL;
+
+        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
+        VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16);
+
+        gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
+
+        VBOX_UTF16_FREE(keyTypeUtf16);
+        VBOX_UTF16_FREE(valueTypeUtf16);
+
+    } else if ((guiPresent == 0) && (sdlPresent == 1)) {
+        /* store extradata key that frontend is set to sdl */
+        PRUnichar *keyTypeUtf16      = NULL;
+        PRUnichar *valueTypeUtf16    = NULL;
+        PRUnichar *keyDislpayUtf16   = NULL;
+        PRUnichar *valueDisplayUtf16 = NULL;
+
+        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
+        VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16);
+
+        gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
+
+        VBOX_UTF16_FREE(keyTypeUtf16);
+        VBOX_UTF16_FREE(valueTypeUtf16);
+
+        if (sdlDisplay) {
+            VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
+            VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16);
+
+            gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16,
+                                            valueDisplayUtf16);
+
+            VBOX_UTF16_FREE(keyDislpayUtf16);
+            VBOX_UTF16_FREE(valueDisplayUtf16);
+        }
+
+    } else {
+        /* if all are set then default is gui, with vrdp turned on */
+        PRUnichar *keyTypeUtf16      = NULL;
+        PRUnichar *valueTypeUtf16    = NULL;
+        PRUnichar *keyDislpayUtf16   = NULL;
+        PRUnichar *valueDisplayUtf16 = NULL;
+
+        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
+        VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16);
+
+        gVBoxAPI.UIMachine.SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
+
+        VBOX_UTF16_FREE(keyTypeUtf16);
+        VBOX_UTF16_FREE(valueTypeUtf16);
+
+        if (guiDisplay) {
+            VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
+            VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16);
+
+            gVBoxAPI.UIMachine.SetExtraData(machine, keyDislpayUtf16,
+                                            valueDisplayUtf16);
+
+            VBOX_UTF16_FREE(keyDislpayUtf16);
+            VBOX_UTF16_FREE(valueDisplayUtf16);
+        }
+    }
+
+    VIR_FREE(guiDisplay);
+    VIR_FREE(sdlDisplay);
+}
+
+static void
+vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    IUSBCommon *USBCommon = NULL;
+    size_t i = 0;
+    bool isUSB = false;
+    nsresult rc;
+
+    if (def->nhostdevs == 0)
+        return;
+
+    /* Loop through the devices first and see if you
+     * have a USB Device, only if you have one then
+     * start the USB controller else just proceed as
+     * usual
+     */
+    for (i = 0; i < def->nhostdevs; i++) {
+        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+            continue;
+
+        if (def->hostdevs[i]->source.subsys.type !=
+            VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
+            continue;
+
+        if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
+            !def->hostdevs[i]->source.subsys.u.usb.product)
+            continue;
+
+        VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x",
+                  def->hostdevs[i]->source.subsys.u.usb.vendor,
+                  def->hostdevs[i]->source.subsys.u.usb.product);
+        isUSB = true;
+        break;
+    }
+
+    if (!isUSB)
+        return;
+
+    /* First Start the USB Controller and then loop
+     * to attach USB Devices to it
+     */
+    rc = gVBoxAPI.UIMachine.GetUSBCommon(machine, &USBCommon);
+    if (NS_FAILED(rc) || !USBCommon)
+        return;
+    gVBoxAPI.UIUSBCommon.Enable(USBCommon);
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        char *filtername           = NULL;
+        PRUnichar *filternameUtf16 = NULL;
+        IUSBDeviceFilter *filter   = NULL;
+        PRUnichar *vendorIdUtf16  = NULL;
+        char vendorId[40]         = {0};
+        PRUnichar *productIdUtf16 = NULL;
+        char productId[40]        = {0};
+
+        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+            continue;
+
+        if (def->hostdevs[i]->source.subsys.type !=
+            VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
+            continue;
+
+        /* Zero pad for nice alignment when fewer than 9999
+         * devices.
+         */
+        if (virAsprintf(&filtername, "filter%04zu", i) >= 0) {
+            VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16);
+            VIR_FREE(filtername);
+            gVBoxAPI.UIUSBCommon.CreateDeviceFilter(USBCommon,
+                                                    filternameUtf16,
+                                                    &filter);
+        }
+        VBOX_UTF16_FREE(filternameUtf16);
+
+        if (!filter)
+            continue;
+
+        if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
+            !def->hostdevs[i]->source.subsys.u.usb.product)
+            continue;
+
+        if (def->hostdevs[i]->source.subsys.u.usb.vendor) {
+            snprintf(vendorId, sizeof(vendorId), "%x",
+                     def->hostdevs[i]->source.subsys.u.usb.vendor);
+            VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16);
+            gVBoxAPI.UIUSBDeviceFilter.SetVendorId(filter, vendorIdUtf16);
+            VBOX_UTF16_FREE(vendorIdUtf16);
+        }
+        if (def->hostdevs[i]->source.subsys.u.usb.product) {
+            snprintf(productId, sizeof(productId), "%x",
+                     def->hostdevs[i]->source.subsys.u.usb.product);
+            VBOX_UTF8_TO_UTF16(productId, &productIdUtf16);
+            gVBoxAPI.UIUSBDeviceFilter.SetProductId(filter,
+                                                    productIdUtf16);
+            VBOX_UTF16_FREE(productIdUtf16);
+        }
+        gVBoxAPI.UIUSBDeviceFilter.SetActive(filter, 1);
+        gVBoxAPI.UIUSBCommon.InsertDeviceFilter(USBCommon, i, filter);
+        VBOX_RELEASE(filter);
+    }
+
+    VBOX_RELEASE(USBCommon);
+}
+
+static void
+vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    size_t i;
+    PRUnichar *nameUtf16;
+    PRUnichar *hostPathUtf16;
+    PRBool writable;
+
+    if (def->nfss == 0)
+        return;
+
+    for (i = 0; i < def->nfss; i++) {
+        if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
+            continue;
+
+        VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16);
+        VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16);
+        writable = !def->fss[i]->readonly;
+
+        gVBoxAPI.UIMachine.CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
+                                              writable, PR_FALSE);
+
+        VBOX_UTF16_FREE(nameUtf16);
+        VBOX_UTF16_FREE(hostPathUtf16);
+    }
+}
+
+virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml)
+{
+    VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
+    IMachine       *machine     = NULL;
+    IBIOSSettings  *bios        = NULL;
+    vboxIIDUnion mchiid;
+    virDomainDefPtr def         = NULL;
+    nsresult rc;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+    VBOX_IID_INITIALIZE(&mchiid);
+    if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt,
+                                        1 << VIR_DOMAIN_VIRT_VBOX,
+                                        VIR_DOMAIN_XML_INACTIVE))) {
+        goto cleanup;
+    }
+
+    virUUIDFormat(def->uuid, uuidstr);
+
+    rc = gVBoxAPI.UIVirtualBox.CreateMachine(data, def, &machine, uuidstr);
+
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not define a domain, rc=%08x"), (unsigned)rc);
+        goto cleanup;
+    }
+
+    rc = gVBoxAPI.UIMachine.SetMemorySize(machine,
+                                          VIR_DIV_UP(def->mem.cur_balloon, 1024));
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not set the memory size of the domain to: %llu Kb, "
+                         "rc=%08x"),
+                       def->mem.cur_balloon, (unsigned)rc);
+    }
+
+    if (def->vcpus != def->maxvcpus) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("current vcpu count must equal maximum"));
+    }
+    rc = gVBoxAPI.UIMachine.SetCPUCount(machine, def->maxvcpus);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not set the number of virtual CPUs to: %u, rc=%08x"),
+                       def->maxvcpus, (unsigned)rc);
+    }
+
+    rc = gVBoxAPI.UIMachine.SetCPUProperty(machine, CPUPropertyType_PAE,
+                                           def->features[VIR_DOMAIN_FEATURE_PAE] ==
+                                           VIR_TRISTATE_SWITCH_ON);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not change PAE status to: %s, rc=%08x"),
+                       (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON)
+                       ? _("Enabled") : _("Disabled"), (unsigned)rc);
+    }
+
+    gVBoxAPI.UIMachine.GetBIOSSettings(machine, &bios);
+    if (bios) {
+        rc = gVBoxAPI.UIBIOSSettings.SetACPIEnabled(bios,
+                                                    def->features[VIR_DOMAIN_FEATURE_ACPI] ==
+                                                    VIR_TRISTATE_SWITCH_ON);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("could not change ACPI status to: %s, rc=%08x"),
+                           (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON)
+                           ? _("Enabled") : _("Disabled"), (unsigned)rc);
+        }
+        rc = gVBoxAPI.UIBIOSSettings.SetIOAPICEnabled(bios,
+                                                      def->features[VIR_DOMAIN_FEATURE_APIC] ==
+                                                      VIR_TRISTATE_SWITCH_ON);
+        if (NS_FAILED(rc)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("could not change APIC status to: %s, rc=%08x"),
+                           (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_TRISTATE_SWITCH_ON)
+                           ? _("Enabled") : _("Disabled"), (unsigned)rc);
+        }
+        VBOX_RELEASE(bios);
+    }
+
+    /* Register the machine before attaching other devices to it */
+    rc = gVBoxAPI.UIVirtualBox.RegisterMachine(data->vboxObj, machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("could not define a domain, rc=%08x"), (unsigned)rc);
+        goto cleanup;
+    }
+
+    /* Get the uuid of the machine, currently it is immutable
+     * object so open a session to it and get it back, so that
+     * you can make changes to the machine setting
+     */
+    gVBoxAPI.UIMachine.GetId(machine, &mchiid);
+    gVBoxAPI.UISession.Open(data, &mchiid, machine);
+    gVBoxAPI.UISession.GetMachine(data->vboxSession, &machine);
+
+    vboxSetBootDeviceOrder(def, data, machine);
+    vboxAttachDrives(def, data, machine);
+    vboxAttachSound(def, machine);
+    vboxAttachNetwork(def, data, machine);
+    vboxAttachSerial(def, data, machine);
+    vboxAttachParallel(def, data, machine);
+    vboxAttachVideo(def, machine);
+    vboxAttachDisplay(def, data, machine);
+    vboxAttachUSB(def, data, machine);
+    vboxAttachSharedFolder(def, data, machine);
+
+    /* Save the machine settings made till now and close the
+     * session. also free up the mchiid variable used.
+     */
+    rc = gVBoxAPI.UIMachine.SaveSettings(machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("failed no saving settings, rc=%08x"), (unsigned)rc);
+        goto cleanup;
+    }
+
+    gVBoxAPI.UISession.Close(data->vboxSession);
+    vboxIIDUnalloc(&mchiid);
+
+    ret = virGetDomain(conn, def->name, def->uuid);
+    VBOX_RELEASE(machine);
+
+    virDomainDefFree(def);
+
+    return ret;
+
+ cleanup:
+    VBOX_RELEASE(machine);
+    virDomainDefFree(def);
+    return NULL;
+}
+
+static void
 detachDevices_common(vboxGlobalData *data, vboxIIDUnion *iidu)
 {
     /* Block for checking if HDD's are attched to VM.
diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h
index c4147a1..eedd755 100644
--- a/src/vbox/vbox_common.h
+++ b/src/vbox/vbox_common.h
@@ -158,6 +158,86 @@ struct _vboxArray {
 
 # endif /* !WIN32 */
 
+/* We make the assumption that these enum flags
+ * are compatible in all vbox API version.
+ *
+ * Yes it is, as it has been checked from vbox 2.2 to
+ * vbox 4.3.3. And this rule MAY NOT stands for new
+ * vbox versions.
+ * */
+enum CPUPropertyType
+{
+    CPUPropertyType_Null = 0,
+    CPUPropertyType_PAE = 1,
+    CPUPropertyType_Synthetic = 2,
+};
+
+enum AudioControllerType
+{
+    AudioControllerType_AC97 = 0,
+    AudioControllerType_SB16 = 1
+};
+
+enum ChipsetType
+{
+    ChipsetType_Null = 0,
+    ChipsetType_PIIX3 = 1,
+    ChipsetType_ICH9 = 2
+};
+
+enum NetworkAdapterType
+{
+    NetworkAdapterType_Null = 0,
+    NetworkAdapterType_Am79C970A = 1,
+    NetworkAdapterType_Am79C973 = 2,
+    NetworkAdapterType_I82540EM = 3,
+    NetworkAdapterType_I82543GC = 4,
+    NetworkAdapterType_I82545EM = 5,
+    NetworkAdapterType_Virtio = 6
+};
+
+enum PortMode
+{
+    PortMode_Disconnected = 0,
+    PortMode_HostPipe = 1,
+    PortMode_HostDevice = 2,
+    PortMode_RawFile = 3
+};
+
+enum DeviceType
+{
+    DeviceType_Null = 0,
+    DeviceType_Floppy = 1,
+    DeviceType_DVD = 2,
+    DeviceType_HardDisk = 3,
+    DeviceType_Network = 4,
+    DeviceType_USB = 5,
+    DeviceType_SharedFolder = 6
+};
+
+enum StorageBus
+{
+    StorageBus_Null = 0,
+    StorageBus_IDE = 1,
+    StorageBus_SATA = 2,
+    StorageBus_SCSI = 3,
+    StorageBus_Floppy = 4,
+    StorageBus_SAS = 5
+};
+
+enum AccessMode
+{
+    AccessMode_ReadOnly = 1,
+    AccessMode_ReadWrite = 2
+};
+
+enum MediumType
+{
+    MediumType_Normal = 0,
+    MediumType_Immutable = 1,
+    MediumType_Writethrough = 2,
+};
+
 /* Simplied definitions in vbox_CAPI_*.h */
 
 typedef void const *PCVBOXXPCOM;
@@ -168,5 +248,15 @@ typedef nsISupports IConsole;
 typedef nsISupports IProgress;
 typedef nsISupports IMachine;
 typedef nsISupports ISystemProperties;
+typedef nsISupports IBIOSSettings;
+typedef nsISupports IAudioAdapter;
+typedef nsISupports INetworkAdapter;
+typedef nsISupports ISerialPort;
+typedef nsISupports IParallelPort;
+typedef nsISupports IVRDxServer;
+typedef nsISupports IUSBCommon;
+typedef nsISupports IUSBDeviceFilter;
+typedef nsISupports IMedium;
+typedef nsISupports IStorageController;
 
 #endif /* VBOX_COMMON_H */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 86c02f1..537616d 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -89,6 +89,19 @@
 
 /* Include this *last* or we'll get the wrong vbox_CAPI_*.h. */
 #include "vbox_glue.h"
+
+#if VBOX_API_VERSION < 4000000
+typedef IVRDPServer IVRDxServer;
+#else /* VBOX_API_VERSION >= 4000000 */
+typedef IVRDEServer IVRDxServer;
+#endif /* VBOX_API_VERSION >= 4000000 */
+
+#if VBOX_API_VERSION < 4003000
+typedef IUSBController IUSBCommon;
+#else /* VBOX_API_VERSION >= 4003000 */
+typedef IUSBDeviceFilters IUSBCommon;
+#endif /* VBOX_API_VERSION >= 4003000 */
+
 #include "vbox_uniformed_api.h"
 
 #define VIR_FROM_THIS                   VIR_FROM_VBOX
@@ -252,7 +265,6 @@ static vboxGlobalData *g_pVBoxGlobalData = NULL;
 
 #endif /* VBOX_API_VERSION >= 4000000 */
 
-static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 static int vboxDomainCreate(virDomainPtr dom);
 
 #if VBOX_API_VERSION > 2002000 && VBOX_API_VERSION < 4000000
@@ -660,7 +672,9 @@ _vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu,
     vboxIIDFromArrayItem_v3_x(data, iid, array, idx)
 # define DEBUGIID(msg, strUtf16) DEBUGPRUnichar(msg, strUtf16)
 
-# if VBOX_API_VERSION >= 3001000
+#endif /* !(VBOX_API_VERSION == 2002000) */
+
+#if VBOX_API_VERSION >= 3001000
 
 /**
  * function to generate the name for medium,
@@ -738,6 +752,8 @@ static char *vboxGenerateMediumName(PRUint32  storageBus,
  * @param       deviceSlot      Output slot number
  *
  */
+# if VBOX_API_VERSION < 4000000
+/* Only 3.x will use this function. */
 static bool vboxGetDeviceDetails(const char *deviceName,
                                  PRUint32   *aMaxPortPerInst,
                                  PRUint32   *aMaxSlotPerPort,
@@ -782,6 +798,7 @@ static bool vboxGetDeviceDetails(const char *deviceName,
 
     return true;
 }
+# endif /* VBOX_API_VERSION < 4000000 */
 
 /**
  * function to get the values for max port per
@@ -876,9 +893,7 @@ static PRUnichar *PRUnicharFromInt(int n) {
     return strUtf16;
 }
 
-# endif /* VBOX_API_VERSION >= 3001000 */
-
-#endif /* !(VBOX_API_VERSION == 2002000) */
+#endif /* VBOX_API_VERSION >= 3001000 */
 
 static PRUnichar *
 vboxSocketFormatAddrUtf16(vboxGlobalData *data, virSocketAddrPtr addr)
@@ -3302,67 +3317,14 @@ static int vboxDomainCreate(virDomainPtr dom)
     return vboxDomainCreateWithFlags(dom, 0);
 }
 
-static void
-vboxSetBootDeviceOrder(virDomainDefPtr def, vboxGlobalData *data,
-                       IMachine *machine)
-{
-    ISystemProperties *systemProperties = NULL;
-    PRUint32 maxBootPosition            = 0;
-    size_t i = 0;
-
-    VIR_DEBUG("def->os.type             %s", def->os.type);
-    VIR_DEBUG("def->os.arch             %s", virArchToString(def->os.arch));
-    VIR_DEBUG("def->os.machine          %s", def->os.machine);
-    VIR_DEBUG("def->os.nBootDevs        %zu", def->os.nBootDevs);
-    VIR_DEBUG("def->os.bootDevs[0]      %d", def->os.bootDevs[0]);
-    VIR_DEBUG("def->os.bootDevs[1]      %d", def->os.bootDevs[1]);
-    VIR_DEBUG("def->os.bootDevs[2]      %d", def->os.bootDevs[2]);
-    VIR_DEBUG("def->os.bootDevs[3]      %d", def->os.bootDevs[3]);
-    VIR_DEBUG("def->os.init             %s", def->os.init);
-    VIR_DEBUG("def->os.kernel           %s", def->os.kernel);
-    VIR_DEBUG("def->os.initrd           %s", def->os.initrd);
-    VIR_DEBUG("def->os.cmdline          %s", def->os.cmdline);
-    VIR_DEBUG("def->os.root             %s", def->os.root);
-    VIR_DEBUG("def->os.loader           %s", def->os.loader);
-    VIR_DEBUG("def->os.bootloader       %s", def->os.bootloader);
-    VIR_DEBUG("def->os.bootloaderArgs   %s", def->os.bootloaderArgs);
-
-    data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
-    if (systemProperties) {
-        systemProperties->vtbl->GetMaxBootPosition(systemProperties,
-                                                   &maxBootPosition);
-        VBOX_RELEASE(systemProperties);
-        systemProperties = NULL;
-    }
-
-    /* Clear the defaults first */
-    for (i = 0; i < maxBootPosition; i++) {
-        machine->vtbl->SetBootOrder(machine, i+1, DeviceType_Null);
-    }
-
-    for (i = 0; (i < def->os.nBootDevs) && (i < maxBootPosition); i++) {
-        PRUint32 device = DeviceType_Null;
-
-        if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_FLOPPY) {
-            device = DeviceType_Floppy;
-        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_CDROM) {
-            device = DeviceType_DVD;
-        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_DISK) {
-            device = DeviceType_HardDisk;
-        } else if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
-            device = DeviceType_Network;
-        }
-        machine->vtbl->SetBootOrder(machine, i+1, device);
-    }
-}
+#if VBOX_API_VERSION < 3001000
 
 static void
-vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
 {
     size_t i;
     nsresult rc;
 
-#if VBOX_API_VERSION < 3001000
     if (def->ndisks == 0)
         return;
 
@@ -3599,7 +3561,16 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
             }
         }
     }
-#else  /* VBOX_API_VERSION >= 3001000 */
+}
+
+#elif VBOX_API_VERSION < 4000000
+
+static void
+_vboxAttachDrivesOld(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+{
+    size_t i;
+    nsresult rc;
+
     PRUint32 maxPortPerInst[StorageBus_Floppy + 1] = {};
     PRUint32 maxSlotPerPort[StorageBus_Floppy + 1] = {};
     PRUnichar *storageCtlName = NULL;
@@ -3675,9 +3646,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
             PRUnichar *mediumFileUtf16 = NULL;
             PRUint32   storageBus      = StorageBus_Null;
             PRUint32   deviceType      = DeviceType_Null;
-# if VBOX_API_VERSION >= 4000000
-            PRUint32   accessMode      = AccessMode_ReadOnly;
-# endif
             PRInt32    deviceInst      = 0;
             PRInt32    devicePort      = 0;
             PRInt32    deviceSlot      = 0;
@@ -3686,47 +3654,26 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
 
             if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
                 deviceType = DeviceType_HardDisk;
-# if VBOX_API_VERSION < 4000000
                 data->vboxObj->vtbl->FindHardDisk(data->vboxObj,
                                                   mediumFileUtf16, &medium);
-# else
-                accessMode = AccessMode_ReadWrite;
-# endif
             } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
                 deviceType = DeviceType_DVD;
-# if VBOX_API_VERSION < 4000000
                 data->vboxObj->vtbl->FindDVDImage(data->vboxObj,
                                                   mediumFileUtf16, &medium);
-# else
-                accessMode = AccessMode_ReadOnly;
-# endif
             } else if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
                 deviceType = DeviceType_Floppy;
-# if VBOX_API_VERSION < 4000000
                 data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
                                                      mediumFileUtf16, &medium);
-# else
-                accessMode = AccessMode_ReadWrite;
-# endif
             } else {
                 VBOX_UTF16_FREE(mediumFileUtf16);
                 continue;
             }
 
-# if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-            data->vboxObj->vtbl->FindMedium(data->vboxObj, mediumFileUtf16,
-                                            deviceType, &medium);
-# elif VBOX_API_VERSION >= 4002000
-            data->vboxObj->vtbl->OpenMedium(data->vboxObj, mediumFileUtf16,
-                                            deviceType, accessMode, PR_FALSE, &medium);
-# endif
-
             if (!medium) {
                 PRUnichar *mediumEmpty = NULL;
 
                 VBOX_UTF8_TO_UTF16("", &mediumEmpty);
 
-# if VBOX_API_VERSION < 4000000
                 if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
                     rc = data->vboxObj->vtbl->OpenHardDisk(data->vboxObj,
                                                            mediumFileUtf16,
@@ -3751,19 +3698,6 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
                 } else {
                     rc = 0;
                 }
-# elif VBOX_API_VERSION == 4000000
-                rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj,
-                                                     mediumFileUtf16,
-                                                     deviceType, accessMode,
-                                                     &medium);
-# elif VBOX_API_VERSION >= 4001000
-                rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj,
-                                                     mediumFileUtf16,
-                                                     deviceType, accessMode,
-                                                     false,
-                                                     &medium);
-# endif /* VBOX_API_VERSION >= 4001000 */
-
                 VBOX_UTF16_FREE(mediumEmpty);
             }
 
@@ -3836,11 +3770,7 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
                                              devicePort,
                                              deviceSlot,
                                              deviceType,
-# if VBOX_API_VERSION < 4000000
                                              mediumUUID);
-# else /* VBOX_API_VERSION >= 4000000 */
-                                             medium);
-# endif /* VBOX_API_VERSION >= 4000000 */
 
             if (NS_FAILED(rc)) {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3857,1421 +3787,510 @@ vboxAttachDrives(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
             VBOX_UTF16_FREE(storageCtlName);
         }
     }
-#endif /* VBOX_API_VERSION >= 3001000 */
 }
 
-static void
-vboxAttachSound(virDomainDefPtr def, IMachine *machine)
-{
-    nsresult rc;
-
-    /* Check if def->nsounds is one as VirtualBox currently supports
-     * only one sound card
-     */
-    if (def->nsounds == 1) {
-        IAudioAdapter *audioAdapter = NULL;
-
-        machine->vtbl->GetAudioAdapter(machine, &audioAdapter);
-        if (audioAdapter) {
-            rc = audioAdapter->vtbl->SetEnabled(audioAdapter, 1);
-            if (NS_SUCCEEDED(rc)) {
-                if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_SB16) {
-                    audioAdapter->vtbl->SetAudioController(audioAdapter,
-                                                           AudioControllerType_SB16);
-                } else if (def->sounds[0]->model == VIR_DOMAIN_SOUND_MODEL_AC97) {
-                    audioAdapter->vtbl->SetAudioController(audioAdapter,
-                                                           AudioControllerType_AC97);
-                }
-            }
-            VBOX_RELEASE(audioAdapter);
-        }
-    }
-}
+#else /* VBOX_API_VERSION >= 4000000 */
 
 static void
-vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+_vboxAttachDrivesOld(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                     vboxGlobalData *data ATTRIBUTE_UNUSED,
+                     IMachine *machine ATTRIBUTE_UNUSED)
 {
-    ISystemProperties *systemProperties = NULL;
-#if VBOX_API_VERSION >= 4001000
-    PRUint32 chipsetType                = ChipsetType_Null;
-#endif /* VBOX_API_VERSION >= 4001000 */
-    PRUint32 networkAdapterCount        = 0;
-    size_t i = 0;
-
-#if VBOX_API_VERSION >= 4001000
-    machine->vtbl->GetChipsetType(machine, &chipsetType);
-#endif /* VBOX_API_VERSION >= 4001000 */
+    vboxUnsupported();
+}
 
-    data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
-    if (systemProperties) {
-#if VBOX_API_VERSION < 4001000
-        systemProperties->vtbl->GetNetworkAdapterCount(systemProperties,
-                                                       &networkAdapterCount);
-#else  /* VBOX_API_VERSION >= 4000000 */
-        systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipsetType,
-                                                      &networkAdapterCount);
 #endif /* VBOX_API_VERSION >= 4000000 */
-        VBOX_RELEASE(systemProperties);
-        systemProperties = NULL;
-    }
-
-    VIR_DEBUG("Number of Network Cards to be connected: %zu", def->nnets);
-    VIR_DEBUG("Number of Network Cards available: %d", networkAdapterCount);
-
-    for (i = 0; (i < def->nnets) && (i < networkAdapterCount); i++) {
-        INetworkAdapter *adapter = NULL;
-        PRUint32 adapterType     = NetworkAdapterType_Null;
-        char macaddr[VIR_MAC_STRING_BUFLEN] = {0};
-        char macaddrvbox[VIR_MAC_STRING_BUFLEN - 5] = {0};
-
-        virMacAddrFormat(&def->nets[i]->mac, macaddr);
-        snprintf(macaddrvbox, VIR_MAC_STRING_BUFLEN - 5,
-                 "%02X%02X%02X%02X%02X%02X",
-                 def->nets[i]->mac.addr[0],
-                 def->nets[i]->mac.addr[1],
-                 def->nets[i]->mac.addr[2],
-                 def->nets[i]->mac.addr[3],
-                 def->nets[i]->mac.addr[4],
-                 def->nets[i]->mac.addr[5]);
-        macaddrvbox[VIR_MAC_STRING_BUFLEN - 6] = '\0';
-
-        VIR_DEBUG("NIC(%zu): Type:   %d", i, def->nets[i]->type);
-        VIR_DEBUG("NIC(%zu): Model:  %s", i, def->nets[i]->model);
-        VIR_DEBUG("NIC(%zu): Mac:    %s", i, macaddr);
-        VIR_DEBUG("NIC(%zu): ifname: %s", i, def->nets[i]->ifname);
-        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
-            VIR_DEBUG("NIC(%zu): name:    %s", i, def->nets[i]->data.network.name);
-        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
-            VIR_DEBUG("NIC(%zu): name:   %s", i, def->nets[i]->data.internal.name);
-        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
-            VIR_DEBUG("NIC(%zu): NAT.", i);
-        } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-            VIR_DEBUG("NIC(%zu): brname: %s", i, def->nets[i]->data.bridge.brname);
-            VIR_DEBUG("NIC(%zu): script: %s", i, def->nets[i]->script);
-            VIR_DEBUG("NIC(%zu): ipaddr: %s", i, def->nets[i]->data.bridge.ipaddr);
-        }
-
-        machine->vtbl->GetNetworkAdapter(machine, i, &adapter);
-        if (adapter) {
-            PRUnichar *MACAddress = NULL;
-
-            adapter->vtbl->SetEnabled(adapter, 1);
-
-            if (def->nets[i]->model) {
-                if (STRCASEEQ(def->nets[i]->model, "Am79C970A")) {
-                    adapterType = NetworkAdapterType_Am79C970A;
-                } else if (STRCASEEQ(def->nets[i]->model, "Am79C973")) {
-                    adapterType = NetworkAdapterType_Am79C973;
-                } else if (STRCASEEQ(def->nets[i]->model, "82540EM")) {
-                    adapterType = NetworkAdapterType_I82540EM;
-                } else if (STRCASEEQ(def->nets[i]->model, "82545EM")) {
-                    adapterType = NetworkAdapterType_I82545EM;
-                } else if (STRCASEEQ(def->nets[i]->model, "82543GC")) {
-                    adapterType = NetworkAdapterType_I82543GC;
-#if VBOX_API_VERSION >= 3001000
-                } else if (STRCASEEQ(def->nets[i]->model, "virtio")) {
-                    adapterType = NetworkAdapterType_Virtio;
-#endif /* VBOX_API_VERSION >= 3001000 */
-                }
-            } else {
-                adapterType = NetworkAdapterType_Am79C973;
-            }
-
-            adapter->vtbl->SetAdapterType(adapter, adapterType);
-
-            if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
-                PRUnichar *hostInterface = NULL;
-                /* Bridged Network */
-
-#if VBOX_API_VERSION < 4001000
-                adapter->vtbl->AttachToBridgedInterface(adapter);
-#else /* VBOX_API_VERSION >= 4001000 */
-                adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged);
-#endif /* VBOX_API_VERSION >= 4001000 */
-
-                if (def->nets[i]->data.bridge.brname) {
-                    VBOX_UTF8_TO_UTF16(def->nets[i]->data.bridge.brname,
-                                       &hostInterface);
-#if VBOX_API_VERSION < 4001000
-                    adapter->vtbl->SetHostInterface(adapter, hostInterface);
-#else /* VBOX_API_VERSION >= 4001000 */
-                    adapter->vtbl->SetBridgedInterface(adapter, hostInterface);
-#endif /* VBOX_API_VERSION >= 4001000 */
-                    VBOX_UTF16_FREE(hostInterface);
-                }
-            } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_INTERNAL) {
-                PRUnichar *internalNetwork = NULL;
-                /* Internal Network */
-
-#if VBOX_API_VERSION < 4001000
-                adapter->vtbl->AttachToInternalNetwork(adapter);
-#else /* VBOX_API_VERSION >= 4001000 */
-                adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal);
-#endif /* VBOX_API_VERSION >= 4001000 */
-
-                if (def->nets[i]->data.internal.name) {
-                    VBOX_UTF8_TO_UTF16(def->nets[i]->data.internal.name,
-                                       &internalNetwork);
-                    adapter->vtbl->SetInternalNetwork(adapter, internalNetwork);
-                    VBOX_UTF16_FREE(internalNetwork);
-                }
-            } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
-                PRUnichar *hostInterface = NULL;
-                /* Host Only Networking (currently only vboxnet0 available
-                 * on *nix and mac, on windows you can create and configure
-                 * as many as you want)
-                 */
-#if VBOX_API_VERSION < 4001000
-                adapter->vtbl->AttachToHostOnlyInterface(adapter);
-#else /* VBOX_API_VERSION >= 4001000 */
-                adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly);
-#endif /* VBOX_API_VERSION >= 4001000 */
-
-                if (def->nets[i]->data.network.name) {
-                    VBOX_UTF8_TO_UTF16(def->nets[i]->data.network.name,
-                                       &hostInterface);
-#if VBOX_API_VERSION < 4001000
-                    adapter->vtbl->SetHostInterface(adapter, hostInterface);
-#else /* VBOX_API_VERSION >= 4001000 */
-                    adapter->vtbl->SetHostOnlyInterface(adapter, hostInterface);
-#endif /* VBOX_API_VERSION >= 4001000 */
-                    VBOX_UTF16_FREE(hostInterface);
-                }
-            } else if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_USER) {
-                /* NAT */
-#if VBOX_API_VERSION < 4001000
-                adapter->vtbl->AttachToNAT(adapter);
-#else /* VBOX_API_VERSION >= 4001000 */
-                adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT);
-#endif /* VBOX_API_VERSION >= 4001000 */
-            } else {
-                /* else always default to NAT if we don't understand
-                 * what option is been passed to us
-                 */
-#if VBOX_API_VERSION < 4001000
-                adapter->vtbl->AttachToNAT(adapter);
-#else /* VBOX_API_VERSION >= 4001000 */
-                adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT);
-#endif /* VBOX_API_VERSION >= 4001000 */
-            }
-
-            VBOX_UTF8_TO_UTF16(macaddrvbox, &MACAddress);
-            adapter->vtbl->SetMACAddress(adapter, MACAddress);
-            VBOX_UTF16_FREE(MACAddress);
-        }
-    }
-}
 
-static void
-vboxAttachSerial(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+static int
+vboxDomainUndefine(virDomainPtr dom)
 {
-    ISystemProperties *systemProperties = NULL;
-    PRUint32 serialPortCount            = 0;
-    size_t i = 0;
-
-    data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
-    if (systemProperties) {
-        systemProperties->vtbl->GetSerialPortCount(systemProperties,
-                                                   &serialPortCount);
-        VBOX_RELEASE(systemProperties);
-        systemProperties = NULL;
-    }
-
-    VIR_DEBUG("Number of Serial Ports to be connected: %zu", def->nserials);
-    VIR_DEBUG("Number of Serial Ports available: %d", serialPortCount);
-    for (i = 0; (i < def->nserials) && (i < serialPortCount); i++) {
-        ISerialPort *serialPort = NULL;
-
-        VIR_DEBUG("SerialPort(%zu): Type: %d", i, def->serials[i]->source.type);
-        VIR_DEBUG("SerialPort(%zu): target.port: %d", i,
-              def->serials[i]->target.port);
-
-        machine->vtbl->GetSerialPort(machine, i, &serialPort);
-        if (serialPort) {
-            PRUnichar *pathUtf16 = NULL;
-
-            serialPort->vtbl->SetEnabled(serialPort, 1);
-
-            if (def->serials[i]->source.data.file.path) {
-                VBOX_UTF8_TO_UTF16(def->serials[i]->source.data.file.path,
-                                   &pathUtf16);
-                serialPort->vtbl->SetPath(serialPort, pathUtf16);
-            }
-
-            /* For now hard code the serial ports to COM1 and COM2,
-             * COM1 (Base Addr: 0x3F8 (decimal: 1016), IRQ: 4)
-             * COM2 (Base Addr: 0x2F8 (decimal:  760), IRQ: 3)
-             * TODO: make this more flexible
-             */
-            /* TODO: to improve the libvirt XMl handling so
-             * that def->serials[i]->target.port shows real port
-             * and not always start at 0
-             */
-            if (def->serials[i]->target.port == 0) {
-                serialPort->vtbl->SetIRQ(serialPort, 4);
-                serialPort->vtbl->SetIOBase(serialPort, 1016);
-                VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
-                      i, 4, 1016, def->serials[i]->source.data.file.path);
-            } else if (def->serials[i]->target.port == 1) {
-                serialPort->vtbl->SetIRQ(serialPort, 3);
-                serialPort->vtbl->SetIOBase(serialPort, 760);
-                VIR_DEBUG(" serialPort-%zu irq: %d, iobase 0x%x, path: %s",
-                      i, 3, 760, def->serials[i]->source.data.file.path);
-            }
-
-            if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV) {
-                serialPort->vtbl->SetHostMode(serialPort, PortMode_HostDevice);
-            } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) {
-                serialPort->vtbl->SetHostMode(serialPort, PortMode_HostPipe);
-#if VBOX_API_VERSION >= 3000000
-            } else if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) {
-                serialPort->vtbl->SetHostMode(serialPort, PortMode_RawFile);
-#endif /* VBOX_API_VERSION >= 3000000 */
-            } else {
-                serialPort->vtbl->SetHostMode(serialPort,
-                                              PortMode_Disconnected);
-            }
-
-            VBOX_RELEASE(serialPort);
-            VBOX_UTF16_FREE(pathUtf16);
-        }
-    }
+    return vboxDomainUndefineFlags(dom, 0);
 }
 
-static void
-vboxAttachParallel(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+static int vboxDomainAttachDeviceImpl(virDomainPtr dom,
+                                      const char *xml,
+                                      int mediaChangeOnly ATTRIBUTE_UNUSED)
 {
-    ISystemProperties *systemProperties = NULL;
-    PRUint32 parallelPortCount          = 0;
-    size_t i = 0;
-
-    data->vboxObj->vtbl->GetSystemProperties(data->vboxObj, &systemProperties);
-    if (systemProperties) {
-        systemProperties->vtbl->GetParallelPortCount(systemProperties,
-                                                     &parallelPortCount);
-        VBOX_RELEASE(systemProperties);
-        systemProperties = NULL;
-    }
-
-    VIR_DEBUG("Number of Parallel Ports to be connected: %zu", def->nparallels);
-    VIR_DEBUG("Number of Parallel Ports available: %d", parallelPortCount);
-    for (i = 0; (i < def->nparallels) && (i < parallelPortCount); i++) {
-        IParallelPort *parallelPort = NULL;
-
-        VIR_DEBUG("ParallelPort(%zu): Type: %d", i, def->parallels[i]->source.type);
-        VIR_DEBUG("ParallelPort(%zu): target.port: %d", i,
-              def->parallels[i]->target.port);
-
-        machine->vtbl->GetParallelPort(machine, i, &parallelPort);
-        if (parallelPort) {
-            PRUnichar *pathUtf16 = NULL;
+    VBOX_OBJECT_CHECK(dom->conn, int, -1);
+    IMachine *machine    = NULL;
+    vboxIID iid = VBOX_IID_INITIALIZER;
+    PRUint32 state       = MachineState_Null;
+    virDomainDefPtr def  = NULL;
+    virDomainDeviceDefPtr dev  = NULL;
+    nsresult rc;
 
-            VBOX_UTF8_TO_UTF16(def->parallels[i]->source.data.file.path, &pathUtf16);
+    if (VIR_ALLOC(def) < 0)
+        return ret;
 
-            /* For now hard code the parallel ports to
-             * LPT1 (Base Addr: 0x378 (decimal: 888), IRQ: 7)
-             * LPT2 (Base Addr: 0x278 (decimal: 632), IRQ: 5)
-             * TODO: make this more flexible
-             */
-            if ((def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV)  ||
-                (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY)  ||
-                (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE) ||
-                (def->parallels[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE)) {
-                parallelPort->vtbl->SetPath(parallelPort, pathUtf16);
-                if (i == 0) {
-                    parallelPort->vtbl->SetIRQ(parallelPort, 7);
-                    parallelPort->vtbl->SetIOBase(parallelPort, 888);
-                    VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
-                          i, 7, 888, def->parallels[i]->source.data.file.path);
-                } else if (i == 1) {
-                    parallelPort->vtbl->SetIRQ(parallelPort, 5);
-                    parallelPort->vtbl->SetIOBase(parallelPort, 632);
-                    VIR_DEBUG(" parallePort-%zu irq: %d, iobase 0x%x, path: %s",
-                          i, 5, 632, def->parallels[i]->source.data.file.path);
-                }
-            }
+    if (VIR_STRDUP(def->os.type, "hvm") < 0)
+        goto cleanup;
 
-            /* like serial port, parallel port can't be enabled unless
-             * correct IRQ and IOBase values are specified.
-             */
-            parallelPort->vtbl->SetEnabled(parallelPort, 1);
+    dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
+                                  VIR_DOMAIN_XML_INACTIVE);
+    if (dev == NULL)
+        goto cleanup;
 
-            VBOX_RELEASE(parallelPort);
-            VBOX_UTF16_FREE(pathUtf16);
-        }
+    vboxIIDFromUUID(&iid, dom->uuid);
+    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_NO_DOMAIN, "%s",
+                       _("no domain with matching uuid"));
+        goto cleanup;
     }
-}
 
-static void
-vboxAttachVideo(virDomainDefPtr def, IMachine *machine)
-{
-    if ((def->nvideos == 1) &&
-        (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_VBOX)) {
-        machine->vtbl->SetVRAMSize(machine,
-                                   VIR_DIV_UP(def->videos[0]->vram, 1024));
-        machine->vtbl->SetMonitorCount(machine, def->videos[0]->heads);
-        if (def->videos[0]->accel) {
-            machine->vtbl->SetAccelerate3DEnabled(machine,
-                                                  def->videos[0]->accel->support3d);
-#if VBOX_API_VERSION >= 3001000
-            machine->vtbl->SetAccelerate2DVideoEnabled(machine,
-                                                       def->videos[0]->accel->support2d);
-#endif /* VBOX_API_VERSION >= 3001000 */
+    if (machine) {
+        machine->vtbl->GetState(machine, &state);
+
+        if ((state == MachineState_Running) ||
+            (state == MachineState_Paused)) {
+            rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
         } else {
-            machine->vtbl->SetAccelerate3DEnabled(machine, 0);
-#if VBOX_API_VERSION >= 3001000
-            machine->vtbl->SetAccelerate2DVideoEnabled(machine, 0);
-#endif /* VBOX_API_VERSION >= 3001000 */
+            rc = VBOX_SESSION_OPEN(iid.value, machine);
         }
-    }
-}
-
-static void
-vboxAttachDisplay(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
-{
-    int vrdpPresent  = 0;
-    int sdlPresent   = 0;
-    int guiPresent   = 0;
-    char *guiDisplay = NULL;
-    char *sdlDisplay = NULL;
-    size_t i = 0;
-
-    for (i = 0; i < def->ngraphics; i++) {
-#if VBOX_API_VERSION < 4000000
-        IVRDPServer *VRDxServer = NULL;
-#else /* VBOX_API_VERSION >= 4000000 */
-        IVRDEServer *VRDxServer = NULL;
-#endif /* VBOX_API_VERSION >= 4000000 */
-
-        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) &&
-            (vrdpPresent == 0)) {
+        if (NS_SUCCEEDED(rc)) {
+            rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
+            if (NS_SUCCEEDED(rc) && machine) {
+                if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+#if VBOX_API_VERSION < 3001000
+                    const char *src = virDomainDiskGetSource(dev->data.disk);
+                    int type = virDomainDiskGetType(dev->data.disk);
 
-            vrdpPresent = 1;
-#if VBOX_API_VERSION < 4000000
-            machine->vtbl->GetVRDPServer(machine, &VRDxServer);
-#else /* VBOX_API_VERSION >= 4000000 */
-            machine->vtbl->GetVRDEServer(machine, &VRDxServer);
-#endif /* VBOX_API_VERSION >= 4000000 */
-            if (VRDxServer) {
-                const char *listenAddr
-                    = virDomainGraphicsListenGetAddress(def->graphics[i], 0);
+                    if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+                        if (type == VIR_STORAGE_TYPE_FILE && src) {
+                            IDVDDrive *dvdDrive = NULL;
+                            /* Currently CDROM/DVD Drive is always IDE
+                             * Secondary Master so neglecting the following
+                             * parameter dev->data.disk->bus
+                             */
+                            machine->vtbl->GetDVDDrive(machine, &dvdDrive);
+                            if (dvdDrive) {
+                                IDVDImage *dvdImage          = NULL;
+                                PRUnichar *dvdfileUtf16      = NULL;
+                                vboxIID dvduuid = VBOX_IID_INITIALIZER;
+                                vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER;
 
-                VRDxServer->vtbl->SetEnabled(VRDxServer, PR_TRUE);
-                VIR_DEBUG("VRDP Support turned ON.");
+                                VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16);
 
-#if VBOX_API_VERSION < 3001000
-                if (def->graphics[i]->data.rdp.port) {
-                    VRDxServer->vtbl->SetPort(VRDxServer,
-                                              def->graphics[i]->data.rdp.port);
-                    VIR_DEBUG("VRDP Port changed to: %d",
-                          def->graphics[i]->data.rdp.port);
-                } else if (def->graphics[i]->data.rdp.autoport) {
-                    /* Setting the port to 0 will reset its value to
-                     * the default one which is 3389 currently
-                     */
-                    VRDxServer->vtbl->SetPort(VRDxServer, 0);
-                    VIR_DEBUG("VRDP Port changed to default, which is 3389 currently");
-                }
-#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */
-                PRUnichar *portUtf16 = NULL;
-                portUtf16 = PRUnicharFromInt(def->graphics[i]->data.rdp.port);
-                VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16);
-                VBOX_UTF16_FREE(portUtf16);
-#else /* VBOX_API_VERSION >= 4000000 */
-                PRUnichar *VRDEPortsKey = NULL;
-                PRUnichar *VRDEPortsValue = NULL;
-                VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey);
-                VRDEPortsValue = PRUnicharFromInt(def->graphics[i]->data.rdp.port);
-                VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey,
-                                                  VRDEPortsValue);
-                VBOX_UTF16_FREE(VRDEPortsKey);
-                VBOX_UTF16_FREE(VRDEPortsValue);
-#endif /* VBOX_API_VERSION >= 4000000 */
+                                data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage);
+                                if (!dvdImage) {
+                                    data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage);
+                                }
+                                if (dvdImage) {
+                                    rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value);
+                                    if (NS_FAILED(rc)) {
+                                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                       _("can't get the uuid of the file to "
+                                                         "be attached to cdrom: %s, rc=%08x"),
+                                                       src, (unsigned)rc);
+                                    } else {
+                                        /* unmount the previous mounted image */
+                                        dvdDrive->vtbl->Unmount(dvdDrive);
+                                        rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value);
+                                        if (NS_FAILED(rc)) {
+                                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                           _("could not attach the file to cdrom: %s, rc=%08x"),
+                                                           src, (unsigned)rc);
+                                        } else {
+                                            ret = 0;
+                                            DEBUGIID("CD/DVD Image UUID:", dvduuid.value);
+                                        }
+                                    }
 
-                if (def->graphics[i]->data.rdp.replaceUser) {
-                    VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer,
-                                                               PR_TRUE);
-                    VIR_DEBUG("VRDP set to reuse single connection");
-                }
+                                    VBOX_MEDIUM_RELEASE(dvdImage);
+                                }
+                                vboxIIDUnalloc(&dvduuid);
+                                VBOX_UTF16_FREE(dvdfileUtf16);
+                                VBOX_RELEASE(dvdDrive);
+                            }
+                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
+                        }
+                    } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+                        if (type == VIR_STORAGE_TYPE_FILE && src) {
+                            IFloppyDrive *floppyDrive;
+                            machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
+                            if (floppyDrive) {
+                                rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1);
+                                if (NS_SUCCEEDED(rc)) {
+                                    IFloppyImage *floppyImage   = NULL;
+                                    PRUnichar *fdfileUtf16      = NULL;
+                                    vboxIID fduuid = VBOX_IID_INITIALIZER;
+                                    vboxIID fdemptyuuid = VBOX_IID_INITIALIZER;
+                                    VBOX_UTF8_TO_UTF16(src, &fdfileUtf16);
+                                    rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
+                                                                              fdfileUtf16,
+                                                                              &floppyImage);
 
-                if (def->graphics[i]->data.rdp.multiUser) {
-                    VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer,
-                                                              PR_TRUE);
-                    VIR_DEBUG("VRDP set to allow multiple connection");
-                }
+                                    if (!floppyImage) {
+                                        data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj,
+                                                                             fdfileUtf16,
+                                                                             fdemptyuuid.value,
+                                                                             &floppyImage);
+                                    }
 
-                if (listenAddr) {
-#if VBOX_API_VERSION >= 4000000
-                    PRUnichar *netAddressKey = NULL;
-#endif
-                    PRUnichar *netAddressUtf16 = NULL;
+                                    if (floppyImage) {
+                                        rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value);
+                                        if (NS_FAILED(rc)) {
+                                            virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                           _("can't get the uuid of the file to be "
+                                                             "attached to floppy drive: %s, rc=%08x"),
+                                                           src, (unsigned)rc);
+                                        } else {
+                                            rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value);
+                                            if (NS_FAILED(rc)) {
+                                                virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                               _("could not attach the file to floppy drive: %s, rc=%08x"),
+                                                               src, (unsigned)rc);
+                                            } else {
+                                                ret = 0;
+                                                DEBUGIID("attached floppy, UUID:", fduuid.value);
+                                            }
+                                        }
+                                        VBOX_MEDIUM_RELEASE(floppyImage);
+                                    }
+                                    vboxIIDUnalloc(&fduuid);
+                                    VBOX_UTF16_FREE(fdfileUtf16);
+                                }
+                                VBOX_RELEASE(floppyDrive);
+                            }
+                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
+                        }
+                    }
+#else  /* VBOX_API_VERSION >= 3001000 */
+#endif /* VBOX_API_VERSION >= 3001000 */
+                } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+                } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+                    if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+                        if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+                        }
+                    }
+                } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
+                           dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
+                    PRUnichar *nameUtf16;
+                    PRUnichar *hostPathUtf16;
+                    PRBool writable;
+
+                    VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
+                    VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16);
+                    writable = !dev->data.fs->readonly;
 
-                    VBOX_UTF8_TO_UTF16(listenAddr, &netAddressUtf16);
 #if VBOX_API_VERSION < 4000000
-                    VRDxServer->vtbl->SetNetAddress(VRDxServer,
-                                                    netAddressUtf16);
+                    rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
+                                                           writable);
 #else /* VBOX_API_VERSION >= 4000000 */
-                    VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey);
-                    VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey,
-                                                      netAddressUtf16);
-                    VBOX_UTF16_FREE(netAddressKey);
+                    rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
+                                                           writable, PR_FALSE);
 #endif /* VBOX_API_VERSION >= 4000000 */
-                    VIR_DEBUG("VRDP listen address is set to: %s",
-                              listenAddr);
-
-                    VBOX_UTF16_FREE(netAddressUtf16);
-                }
-
-                VBOX_RELEASE(VRDxServer);
-            }
-        }
 
-        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) &&
-            (guiPresent == 0)) {
-            guiPresent = 1;
-            if (VIR_STRDUP(guiDisplay, def->graphics[i]->data.desktop.display) < 0) {
-                /* just don't go to cleanup yet as it is ok to have
-                 * guiDisplay as NULL and we check it below if it
-                 * exist and then only use it there
-                 */
-            }
-        }
+                    if (NS_FAILED(rc)) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("could not attach shared folder '%s', rc=%08x"),
+                                       dev->data.fs->dst, (unsigned)rc);
+                    } else {
+                        ret = 0;
+                    }
 
-        if ((def->graphics[i]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) &&
-            (sdlPresent == 0)) {
-            sdlPresent = 1;
-            if (VIR_STRDUP(sdlDisplay, def->graphics[i]->data.sdl.display) < 0) {
-                /* just don't go to cleanup yet as it is ok to have
-                 * sdlDisplay as NULL and we check it below if it
-                 * exist and then only use it there
-                 */
+                    VBOX_UTF16_FREE(nameUtf16);
+                    VBOX_UTF16_FREE(hostPathUtf16);
+                }
+                machine->vtbl->SaveSettings(machine);
+                VBOX_RELEASE(machine);
             }
+            VBOX_SESSION_CLOSE();
         }
     }
 
-    if ((vrdpPresent == 1) && (guiPresent == 0) && (sdlPresent == 0)) {
-        /* store extradata key that frontend is set to vrdp */
-        PRUnichar *keyTypeUtf16   = NULL;
-        PRUnichar *valueTypeUtf16 = NULL;
-
-        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
-        VBOX_UTF8_TO_UTF16("vrdp", &valueTypeUtf16);
-
-        machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
-
-        VBOX_UTF16_FREE(keyTypeUtf16);
-        VBOX_UTF16_FREE(valueTypeUtf16);
-
-    } else if ((guiPresent == 0) && (sdlPresent == 1)) {
-        /* store extradata key that frontend is set to sdl */
-        PRUnichar *keyTypeUtf16      = NULL;
-        PRUnichar *valueTypeUtf16    = NULL;
-        PRUnichar *keyDislpayUtf16   = NULL;
-        PRUnichar *valueDisplayUtf16 = NULL;
-
-        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
-        VBOX_UTF8_TO_UTF16("sdl", &valueTypeUtf16);
-
-        machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
-
-        VBOX_UTF16_FREE(keyTypeUtf16);
-        VBOX_UTF16_FREE(valueTypeUtf16);
-
-        if (sdlDisplay) {
-            VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
-            VBOX_UTF8_TO_UTF16(sdlDisplay, &valueDisplayUtf16);
-
-            machine->vtbl->SetExtraData(machine, keyDislpayUtf16,
-                                        valueDisplayUtf16);
-
-            VBOX_UTF16_FREE(keyDislpayUtf16);
-            VBOX_UTF16_FREE(valueDisplayUtf16);
-        }
-
-    } else {
-        /* if all are set then default is gui, with vrdp turned on */
-        PRUnichar *keyTypeUtf16      = NULL;
-        PRUnichar *valueTypeUtf16    = NULL;
-        PRUnichar *keyDislpayUtf16   = NULL;
-        PRUnichar *valueDisplayUtf16 = NULL;
+ cleanup:
+    vboxIIDUnalloc(&iid);
+    virDomainDefFree(def);
+    virDomainDeviceDefFree(dev);
+    return ret;
+}
 
-        VBOX_UTF8_TO_UTF16("FRONTEND/Type", &keyTypeUtf16);
-        VBOX_UTF8_TO_UTF16("gui", &valueTypeUtf16);
+static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml)
+{
+    return vboxDomainAttachDeviceImpl(dom, xml, 0);
+}
 
-        machine->vtbl->SetExtraData(machine, keyTypeUtf16, valueTypeUtf16);
+static int
+vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
+                            unsigned int flags)
+{
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
 
-        VBOX_UTF16_FREE(keyTypeUtf16);
-        VBOX_UTF16_FREE(valueTypeUtf16);
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot modify the persistent configuration of a domain"));
+        return -1;
+    }
 
-        if (guiDisplay) {
-            VBOX_UTF8_TO_UTF16("FRONTEND/Display", &keyDislpayUtf16);
-            VBOX_UTF8_TO_UTF16(guiDisplay, &valueDisplayUtf16);
+    return vboxDomainAttachDeviceImpl(dom, xml, 0);
+}
 
-            machine->vtbl->SetExtraData(machine, keyDislpayUtf16,
-                                        valueDisplayUtf16);
+static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
+                                       unsigned int flags)
+{
+    virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT |
+                  VIR_DOMAIN_AFFECT_LIVE |
+                  VIR_DOMAIN_AFFECT_CONFIG, -1);
 
-            VBOX_UTF16_FREE(keyDislpayUtf16);
-            VBOX_UTF16_FREE(valueDisplayUtf16);
-        }
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot modify the persistent configuration of a domain"));
+        return -1;
     }
 
-    VIR_FREE(guiDisplay);
-    VIR_FREE(sdlDisplay);
+    return vboxDomainAttachDeviceImpl(dom, xml, 1);
 }
 
-static void
-vboxAttachUSB(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml)
 {
-#if VBOX_API_VERSION < 4003000
-    IUSBController *USBController = NULL;
-#else
-    IUSBDeviceFilters *USBDeviceFilters = NULL;
-#endif
-    size_t i = 0;
-    bool isUSB = false;
-
-    if (def->nhostdevs == 0)
-        return;
+    VBOX_OBJECT_CHECK(dom->conn, int, -1);
+    IMachine *machine    = NULL;
+    vboxIID iid = VBOX_IID_INITIALIZER;
+    PRUint32 state       = MachineState_Null;
+    virDomainDefPtr def  = NULL;
+    virDomainDeviceDefPtr dev  = NULL;
+    nsresult rc;
 
-    /* Loop through the devices first and see if you
-     * have a USB Device, only if you have one then
-     * start the USB controller else just proceed as
-     * usual
-     */
-    for (i = 0; i < def->nhostdevs; i++) {
-        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
-            continue;
+    if (VIR_ALLOC(def) < 0)
+        return ret;
 
-        if (def->hostdevs[i]->source.subsys.type !=
-            VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
-            continue;
+    if (VIR_STRDUP(def->os.type, "hvm") < 0)
+        goto cleanup;
 
-        if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
-            !def->hostdevs[i]->source.subsys.u.usb.product)
-            continue;
+    dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
+                                  VIR_DOMAIN_XML_INACTIVE);
+    if (dev == NULL)
+        goto cleanup;
 
-        VIR_DEBUG("USB Device detected, VendorId:0x%x, ProductId:0x%x",
-                  def->hostdevs[i]->source.subsys.u.usb.vendor,
-                  def->hostdevs[i]->source.subsys.u.usb.product);
-        isUSB = true;
-        break;
+    vboxIIDFromUUID(&iid, dom->uuid);
+    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_NO_DOMAIN, "%s",
+                       _("no domain with matching uuid"));
+        goto cleanup;
     }
 
-    if (!isUSB)
-        return;
-
-#if VBOX_API_VERSION < 4003000
-    /* First Start the USB Controller and then loop
-     * to attach USB Devices to it
-     */
-    machine->vtbl->GetUSBController(machine, &USBController);
-
-    if (!USBController)
-        return;
+    if (machine) {
+        machine->vtbl->GetState(machine, &state);
 
-    USBController->vtbl->SetEnabled(USBController, 1);
-# if VBOX_API_VERSION < 4002000
-    USBController->vtbl->SetEnabledEhci(USBController, 1);
-# else
-    USBController->vtbl->SetEnabledEHCI(USBController, 1);
-# endif
-#else
-    machine->vtbl->GetUSBDeviceFilters(machine, &USBDeviceFilters);
+        if ((state == MachineState_Running) ||
+            (state == MachineState_Paused)) {
+            rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
+        } else {
+            rc = VBOX_SESSION_OPEN(iid.value, machine);
+        }
 
-    if (!USBDeviceFilters)
-        return;
-#endif
+        if (NS_SUCCEEDED(rc)) {
+            rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
+            if (NS_SUCCEEDED(rc) && machine) {
+                if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
+#if VBOX_API_VERSION < 3001000
+                    int type = virDomainDiskGetType(dev->data.disk);
 
-    for (i = 0; i < def->nhostdevs; i++) {
-        char *filtername           = NULL;
-        PRUnichar *filternameUtf16 = NULL;
-        IUSBDeviceFilter *filter   = NULL;
-        PRUnichar *vendorIdUtf16  = NULL;
-        char vendorId[40]         = {0};
-        PRUnichar *productIdUtf16 = NULL;
-        char productId[40]        = {0};
-
-        if (def->hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
-            continue;
+                    if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
+                        if (type == VIR_STORAGE_TYPE_FILE) {
+                            IDVDDrive *dvdDrive = NULL;
+                            /* Currently CDROM/DVD Drive is always IDE
+                             * Secondary Master so neglecting the following
+                             * parameter dev->data.disk->bus
+                             */
+                            machine->vtbl->GetDVDDrive(machine, &dvdDrive);
+                            if (dvdDrive) {
+                                rc = dvdDrive->vtbl->Unmount(dvdDrive);
+                                if (NS_FAILED(rc)) {
+                                    virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                   _("could not de-attach the mounted ISO, rc=%08x"),
+                                                   (unsigned)rc);
+                                } else {
+                                    ret = 0;
+                                }
+                                VBOX_RELEASE(dvdDrive);
+                            }
+                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
+                        }
+                    } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+                        if (type == VIR_STORAGE_TYPE_FILE) {
+                            IFloppyDrive *floppyDrive;
+                            machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
+                            if (floppyDrive) {
+                                PRBool enabled = PR_FALSE;
 
-        if (def->hostdevs[i]->source.subsys.type !=
-            VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
-            continue;
+                                floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled);
+                                if (enabled) {
+                                    rc = floppyDrive->vtbl->Unmount(floppyDrive);
+                                    if (NS_FAILED(rc)) {
+                                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                                       _("could not attach the file "
+                                                         "to floppy drive, rc=%08x"),
+                                                       (unsigned)rc);
+                                    } else {
+                                        ret = 0;
+                                    }
+                                } else {
+                                    /* If you are here means floppy drive is already unmounted
+                                     * so don't flag error, just say everything is fine and quit
+                                     */
+                                    ret = 0;
+                                }
+                                VBOX_RELEASE(floppyDrive);
+                            }
+                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
+                        }
+                    }
+#else  /* VBOX_API_VERSION >= 3001000 */
+#endif /* VBOX_API_VERSION >= 3001000 */
+                } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
+                } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+                    if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
+                        if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+                        }
+                    }
+                } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
+                           dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
+                    PRUnichar *nameUtf16;
 
-        /* Zero pad for nice alignment when fewer than 9999
-         * devices.
-         */
-        if (virAsprintf(&filtername, "filter%04zu", i) >= 0) {
-            VBOX_UTF8_TO_UTF16(filtername, &filternameUtf16);
-            VIR_FREE(filtername);
-#if VBOX_API_VERSION < 4003000
-            USBController->vtbl->CreateDeviceFilter(USBController,
-                                                    filternameUtf16,
-                                                    &filter);
-#else
-            USBDeviceFilters->vtbl->CreateDeviceFilter(USBDeviceFilters,
-                                                       filternameUtf16,
-                                                       &filter);
-#endif
-        }
-        VBOX_UTF16_FREE(filternameUtf16);
+                    VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
 
-        if (!filter)
-            continue;
+                    rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16);
 
-        if (!def->hostdevs[i]->source.subsys.u.usb.vendor &&
-            !def->hostdevs[i]->source.subsys.u.usb.product)
-            continue;
+                    if (NS_FAILED(rc)) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR,
+                                       _("could not detach shared folder '%s', rc=%08x"),
+                                       dev->data.fs->dst, (unsigned)rc);
+                    } else {
+                        ret = 0;
+                    }
 
-        if (def->hostdevs[i]->source.subsys.u.usb.vendor) {
-            snprintf(vendorId, sizeof(vendorId), "%x",
-                     def->hostdevs[i]->source.subsys.u.usb.vendor);
-            VBOX_UTF8_TO_UTF16(vendorId, &vendorIdUtf16);
-            filter->vtbl->SetVendorId(filter, vendorIdUtf16);
-            VBOX_UTF16_FREE(vendorIdUtf16);
-        }
-        if (def->hostdevs[i]->source.subsys.u.usb.product) {
-            snprintf(productId, sizeof(productId), "%x",
-                     def->hostdevs[i]->source.subsys.u.usb.product);
-            VBOX_UTF8_TO_UTF16(productId, &productIdUtf16);
-            filter->vtbl->SetProductId(filter,
-                                       productIdUtf16);
-            VBOX_UTF16_FREE(productIdUtf16);
-        }
-        filter->vtbl->SetActive(filter, 1);
-#if VBOX_API_VERSION < 4003000
-        USBController->vtbl->InsertDeviceFilter(USBController,
-                                                i,
-                                                filter);
-#else
-        USBDeviceFilters->vtbl->InsertDeviceFilter(USBDeviceFilters,
-                                                   i,
-                                                   filter);
-#endif
-        VBOX_RELEASE(filter);
+                    VBOX_UTF16_FREE(nameUtf16);
+                }
+                machine->vtbl->SaveSettings(machine);
+                VBOX_RELEASE(machine);
+            }
+            VBOX_SESSION_CLOSE();
+        }
     }
 
-#if VBOX_API_VERSION < 4003000
-    VBOX_RELEASE(USBController);
-#else
-    VBOX_RELEASE(USBDeviceFilters);
-#endif
+ cleanup:
+    vboxIIDUnalloc(&iid);
+    virDomainDefFree(def);
+    virDomainDeviceDefFree(dev);
+    return ret;
 }
 
-static void
-vboxAttachSharedFolder(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine)
+static int
+vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
+                            unsigned int flags)
 {
-    size_t i;
-    PRUnichar *nameUtf16;
-    PRUnichar *hostPathUtf16;
-    PRBool writable;
-
-    if (def->nfss == 0)
-        return;
-
-    for (i = 0; i < def->nfss; i++) {
-        if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
-            continue;
-
-        VBOX_UTF8_TO_UTF16(def->fss[i]->dst, &nameUtf16);
-        VBOX_UTF8_TO_UTF16(def->fss[i]->src, &hostPathUtf16);
-        writable = !def->fss[i]->readonly;
-
-#if VBOX_API_VERSION < 4000000
-        machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
-                                          writable);
-#else /* VBOX_API_VERSION >= 4000000 */
-        machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
-                                          writable, PR_FALSE);
-#endif /* VBOX_API_VERSION >= 4000000 */
+    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
 
-        VBOX_UTF16_FREE(nameUtf16);
-        VBOX_UTF16_FREE(hostPathUtf16);
+    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot modify the persistent configuration of a domain"));
+        return -1;
     }
+
+    return vboxDomainDetachDevice(dom, xml);
 }
 
-static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml)
+static int
+vboxDomainSnapshotGetAll(virDomainPtr dom,
+                         IMachine *machine,
+                         ISnapshot ***snapshots)
 {
-    VBOX_OBJECT_CHECK(conn, virDomainPtr, NULL);
-    IMachine       *machine     = NULL;
-    IBIOSSettings  *bios        = NULL;
-    vboxIID iid = VBOX_IID_INITIALIZER;
-    vboxIID mchiid = VBOX_IID_INITIALIZER;
-    virDomainDefPtr def         = NULL;
-    PRUnichar *machineNameUtf16 = NULL;
-#if VBOX_API_VERSION >= 3002000 && VBOX_API_VERSION < 4002000
-    PRBool override             = PR_FALSE;
-#endif
+    vboxIID empty = VBOX_IID_INITIALIZER;
+    ISnapshot **list = NULL;
+    PRUint32 count;
     nsresult rc;
-    char uuidstr[VIR_UUID_STRING_BUFLEN];
-#if VBOX_API_VERSION >= 4002000
-    const char *flagsUUIDPrefix = "UUID=";
-    const char *flagsForceOverwrite = "forceOverwrite=0";
-    const char *flagsSeparator = ",";
-    char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1];
-    PRUnichar *createFlagsUtf16 = NULL;
-#endif
-
-    if (!(def = virDomainDefParseString(xml, data->caps, data->xmlopt,
-                                        1 << VIR_DOMAIN_VIRT_VBOX,
-                                        VIR_DOMAIN_XML_INACTIVE))) {
-        goto cleanup;
-    }
-
-    VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16);
-    vboxIIDFromUUID(&iid, def->uuid);
-    virUUIDFormat(def->uuid, uuidstr);
-
-#if VBOX_API_VERSION < 3002000
-    rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
-                                            machineNameUtf16,
-                                            NULL,
-                                            NULL,
-                                            iid.value,
-                                            &machine);
-#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */
-    rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
-                                            machineNameUtf16,
-                                            NULL,
-                                            NULL,
-                                            iid.value,
-                                            override,
-                                            &machine);
-#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-    rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
-                                            NULL,
-                                            machineNameUtf16,
-                                            NULL,
-                                            iid.value,
-                                            override,
-                                            &machine);
-#else /* VBOX_API_VERSION >= 4002000 */
-    snprintf(createFlags, sizeof(createFlags), "%s%s%s%s",
-             flagsUUIDPrefix,
-             uuidstr,
-             flagsSeparator,
-             flagsForceOverwrite
-            );
-    VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16);
-    rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
-                                            NULL,
-                                            machineNameUtf16,
-                                            0,
-                                            nsnull,
-                                            nsnull,
-                                            createFlagsUtf16,
-                                            &machine);
-#endif /* VBOX_API_VERSION >= 4002000 */
-    VBOX_UTF16_FREE(machineNameUtf16);
+    unsigned int next;
+    unsigned int top;
 
+    rc = machine->vtbl->GetSnapshotCount(machine, &count);
     if (NS_FAILED(rc)) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not define a domain, rc=%08x"), (unsigned)rc);
-        goto cleanup;
+                       _("could not get snapshot count for domain %s"),
+                       dom->name);
+        goto error;
     }
 
-    rc = machine->vtbl->SetMemorySize(machine,
-                                      VIR_DIV_UP(def->mem.cur_balloon, 1024));
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not set the memory size of the domain to: %llu Kb, "
-                         "rc=%08x"),
-                       def->mem.cur_balloon, (unsigned)rc);
-    }
+    if (count == 0)
+        goto out;
 
-    if (def->vcpus != def->maxvcpus) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("current vcpu count must equal maximum"));
-    }
-    rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not set the number of virtual CPUs to: %u, rc=%08x"),
-                       def->maxvcpus, (unsigned)rc);
-    }
+    if (VIR_ALLOC_N(list, count) < 0)
+        goto error;
 
-#if VBOX_API_VERSION < 3001000
-    rc = machine->vtbl->SetPAEEnabled(machine,
-                                      def->features[VIR_DOMAIN_FEATURE_PAE] ==
-                                      VIR_TRISTATE_SWITCH_ON);
-#elif VBOX_API_VERSION == 3001000
-    rc = machine->vtbl->SetCpuProperty(machine, CpuPropertyType_PAE,
-                                       def->features[VIR_DOMAIN_FEATURE_PAE] ==
-                                       VIR_TRISTATE_SWITCH_ON);
-#elif VBOX_API_VERSION >= 3002000
-    rc = machine->vtbl->SetCPUProperty(machine, CPUPropertyType_PAE,
-                                       def->features[VIR_DOMAIN_FEATURE_PAE] ==
-                                       VIR_TRISTATE_SWITCH_ON);
-#endif
-    if (NS_FAILED(rc)) {
+#if VBOX_API_VERSION < 4000000
+    rc = machine->vtbl->GetSnapshot(machine, empty.value, list);
+#else /* VBOX_API_VERSION >= 4000000 */
+    rc = machine->vtbl->FindSnapshot(machine, empty.value, list);
+#endif /* VBOX_API_VERSION >= 4000000 */
+    if (NS_FAILED(rc) || !list[0]) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not change PAE status to: %s, rc=%08x"),
-                       (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_TRISTATE_SWITCH_ON)
-                       ? _("Enabled") : _("Disabled"), (unsigned)rc);
+                       _("could not get root snapshot for domain %s"),
+                       dom->name);
+        goto error;
     }
 
-    machine->vtbl->GetBIOSSettings(machine, &bios);
-    if (bios) {
-        rc = bios->vtbl->SetACPIEnabled(bios,
-                                        def->features[VIR_DOMAIN_FEATURE_ACPI] ==
-                                        VIR_TRISTATE_SWITCH_ON);
-        if (NS_FAILED(rc)) {
+    /* BFS walk through snapshot tree */
+    top = 1;
+    for (next = 0; next < count; next++) {
+        vboxArray children = VBOX_ARRAY_INITIALIZER;
+        size_t i;
+
+        if (!list[next]) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("could not change ACPI status to: %s, rc=%08x"),
-                           (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON)
-                           ? _("Enabled") : _("Disabled"), (unsigned)rc);
+                           _("unexpected number of snapshots < %u"), count);
+            goto error;
         }
-        rc = bios->vtbl->SetIOAPICEnabled(bios,
-                                          def->features[VIR_DOMAIN_FEATURE_APIC] ==
-                                          VIR_TRISTATE_SWITCH_ON);
+
+        rc = vboxArrayGet(&children, list[next],
+                               list[next]->vtbl->GetChildren);
         if (NS_FAILED(rc)) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("could not change APIC status to: %s, rc=%08x"),
-                           (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_TRISTATE_SWITCH_ON)
-                           ? _("Enabled") : _("Disabled"), (unsigned)rc);
+                           "%s", _("could not get children snapshots"));
+            goto error;
         }
-        VBOX_RELEASE(bios);
-    }
-
-    /* Register the machine before attaching other devices to it */
-    rc = data->vboxObj->vtbl->RegisterMachine(data->vboxObj, machine);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not define a domain, rc=%08x"), (unsigned)rc);
-        goto cleanup;
+        for (i = 0; i < children.count; i++) {
+            ISnapshot *child = children.items[i];
+            if (!child)
+                continue;
+            if (top == count) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected number of snapshots > %u"), count);
+                vboxArrayRelease(&children);
+                goto error;
+            }
+            VBOX_ADDREF(child);
+            list[top++] = child;
+        }
+        vboxArrayRelease(&children);
     }
 
-    /* Get the uuid of the machine, currently it is immutable
-     * object so open a session to it and get it back, so that
-     * you can make changes to the machine setting
-     */
-    machine->vtbl->GetId(machine, &mchiid.value);
-    VBOX_SESSION_OPEN(mchiid.value, machine);
-    data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
-
-    vboxSetBootDeviceOrder(def, data, machine);
-    vboxAttachDrives(def, data, machine);
-    vboxAttachSound(def, machine);
-    vboxAttachNetwork(def, data, machine);
-    vboxAttachSerial(def, data, machine);
-    vboxAttachParallel(def, data, machine);
-    vboxAttachVideo(def, machine);
-    vboxAttachDisplay(def, data, machine);
-    vboxAttachUSB(def, data, machine);
-    vboxAttachSharedFolder(def, data, machine);
-
-    /* Save the machine settings made till now and close the
-     * session. also free up the mchiid variable used.
-     */
-    rc = machine->vtbl->SaveSettings(machine);
-    VBOX_SESSION_CLOSE();
-    vboxIIDUnalloc(&mchiid);
-
-    ret = virGetDomain(conn, def->name, def->uuid);
-    VBOX_RELEASE(machine);
-
-    vboxIIDUnalloc(&iid);
-    virDomainDefFree(def);
+ out:
+    *snapshots = list;
+    return count;
 
-    return ret;
+ error:
+    if (list) {
+        for (next = 0; next < count; next++)
+            VBOX_RELEASE(list[next]);
+    }
+    VIR_FREE(list);
 
- cleanup:
-    VBOX_RELEASE(machine);
-    vboxIIDUnalloc(&iid);
-    virDomainDefFree(def);
-    return NULL;
+    return -1;
 }
 
-static int
-vboxDomainUndefine(virDomainPtr dom)
+static ISnapshot *
+vboxDomainSnapshotGet(vboxGlobalData *data,
+                      virDomainPtr dom,
+                      IMachine *machine,
+                      const char *name)
 {
-    return vboxDomainUndefineFlags(dom, 0);
-}
-
-static int vboxDomainAttachDeviceImpl(virDomainPtr dom,
-                                      const char *xml,
-                                      int mediaChangeOnly ATTRIBUTE_UNUSED)
-{
-    VBOX_OBJECT_CHECK(dom->conn, int, -1);
-    IMachine *machine    = NULL;
-    vboxIID iid = VBOX_IID_INITIALIZER;
-    PRUint32 state       = MachineState_Null;
-    virDomainDefPtr def  = NULL;
-    virDomainDeviceDefPtr dev  = NULL;
-    nsresult rc;
-
-    if (VIR_ALLOC(def) < 0)
-        return ret;
-
-    if (VIR_STRDUP(def->os.type, "hvm") < 0)
-        goto cleanup;
-
-    dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
-                                  VIR_DOMAIN_XML_INACTIVE);
-    if (dev == NULL)
-        goto cleanup;
-
-    vboxIIDFromUUID(&iid, dom->uuid);
-    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_NO_DOMAIN, "%s",
-                       _("no domain with matching uuid"));
-        goto cleanup;
-    }
-
-    if (machine) {
-        machine->vtbl->GetState(machine, &state);
-
-        if ((state == MachineState_Running) ||
-            (state == MachineState_Paused)) {
-            rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
-        } else {
-            rc = VBOX_SESSION_OPEN(iid.value, machine);
-        }
-        if (NS_SUCCEEDED(rc)) {
-            rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
-            if (NS_SUCCEEDED(rc) && machine) {
-                if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
-#if VBOX_API_VERSION < 3001000
-                    const char *src = virDomainDiskGetSource(dev->data.disk);
-                    int type = virDomainDiskGetType(dev->data.disk);
-
-                    if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
-                        if (type == VIR_STORAGE_TYPE_FILE && src) {
-                            IDVDDrive *dvdDrive = NULL;
-                            /* Currently CDROM/DVD Drive is always IDE
-                             * Secondary Master so neglecting the following
-                             * parameter dev->data.disk->bus
-                             */
-                            machine->vtbl->GetDVDDrive(machine, &dvdDrive);
-                            if (dvdDrive) {
-                                IDVDImage *dvdImage          = NULL;
-                                PRUnichar *dvdfileUtf16      = NULL;
-                                vboxIID dvduuid = VBOX_IID_INITIALIZER;
-                                vboxIID dvdemptyuuid = VBOX_IID_INITIALIZER;
-
-                                VBOX_UTF8_TO_UTF16(src, &dvdfileUtf16);
-
-                                data->vboxObj->vtbl->FindDVDImage(data->vboxObj, dvdfileUtf16, &dvdImage);
-                                if (!dvdImage) {
-                                    data->vboxObj->vtbl->OpenDVDImage(data->vboxObj, dvdfileUtf16, dvdemptyuuid.value, &dvdImage);
-                                }
-                                if (dvdImage) {
-                                    rc = dvdImage->vtbl->imedium.GetId((IMedium *)dvdImage, &dvduuid.value);
-                                    if (NS_FAILED(rc)) {
-                                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                       _("can't get the uuid of the file to "
-                                                         "be attached to cdrom: %s, rc=%08x"),
-                                                       src, (unsigned)rc);
-                                    } else {
-                                        /* unmount the previous mounted image */
-                                        dvdDrive->vtbl->Unmount(dvdDrive);
-                                        rc = dvdDrive->vtbl->MountImage(dvdDrive, dvduuid.value);
-                                        if (NS_FAILED(rc)) {
-                                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                           _("could not attach the file to cdrom: %s, rc=%08x"),
-                                                           src, (unsigned)rc);
-                                        } else {
-                                            ret = 0;
-                                            DEBUGIID("CD/DVD Image UUID:", dvduuid.value);
-                                        }
-                                    }
-
-                                    VBOX_MEDIUM_RELEASE(dvdImage);
-                                }
-                                vboxIIDUnalloc(&dvduuid);
-                                VBOX_UTF16_FREE(dvdfileUtf16);
-                                VBOX_RELEASE(dvdDrive);
-                            }
-                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
-                        }
-                    } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
-                        if (type == VIR_STORAGE_TYPE_FILE && src) {
-                            IFloppyDrive *floppyDrive;
-                            machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
-                            if (floppyDrive) {
-                                rc = floppyDrive->vtbl->SetEnabled(floppyDrive, 1);
-                                if (NS_SUCCEEDED(rc)) {
-                                    IFloppyImage *floppyImage   = NULL;
-                                    PRUnichar *fdfileUtf16      = NULL;
-                                    vboxIID fduuid = VBOX_IID_INITIALIZER;
-                                    vboxIID fdemptyuuid = VBOX_IID_INITIALIZER;
-                                    VBOX_UTF8_TO_UTF16(src, &fdfileUtf16);
-                                    rc = data->vboxObj->vtbl->FindFloppyImage(data->vboxObj,
-                                                                              fdfileUtf16,
-                                                                              &floppyImage);
-
-                                    if (!floppyImage) {
-                                        data->vboxObj->vtbl->OpenFloppyImage(data->vboxObj,
-                                                                             fdfileUtf16,
-                                                                             fdemptyuuid.value,
-                                                                             &floppyImage);
-                                    }
-
-                                    if (floppyImage) {
-                                        rc = floppyImage->vtbl->imedium.GetId((IMedium *)floppyImage, &fduuid.value);
-                                        if (NS_FAILED(rc)) {
-                                            virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                           _("can't get the uuid of the file to be "
-                                                             "attached to floppy drive: %s, rc=%08x"),
-                                                           src, (unsigned)rc);
-                                        } else {
-                                            rc = floppyDrive->vtbl->MountImage(floppyDrive, fduuid.value);
-                                            if (NS_FAILED(rc)) {
-                                                virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                               _("could not attach the file to floppy drive: %s, rc=%08x"),
-                                                               src, (unsigned)rc);
-                                            } else {
-                                                ret = 0;
-                                                DEBUGIID("attached floppy, UUID:", fduuid.value);
-                                            }
-                                        }
-                                        VBOX_MEDIUM_RELEASE(floppyImage);
-                                    }
-                                    vboxIIDUnalloc(&fduuid);
-                                    VBOX_UTF16_FREE(fdfileUtf16);
-                                }
-                                VBOX_RELEASE(floppyDrive);
-                            }
-                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
-                        }
-                    }
-#else  /* VBOX_API_VERSION >= 3001000 */
-#endif /* VBOX_API_VERSION >= 3001000 */
-                } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
-                } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
-                    if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
-                        if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-                        }
-                    }
-                } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
-                           dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
-                    PRUnichar *nameUtf16;
-                    PRUnichar *hostPathUtf16;
-                    PRBool writable;
-
-                    VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
-                    VBOX_UTF8_TO_UTF16(dev->data.fs->src, &hostPathUtf16);
-                    writable = !dev->data.fs->readonly;
-
-#if VBOX_API_VERSION < 4000000
-                    rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
-                                                           writable);
-#else /* VBOX_API_VERSION >= 4000000 */
-                    rc = machine->vtbl->CreateSharedFolder(machine, nameUtf16, hostPathUtf16,
-                                                           writable, PR_FALSE);
-#endif /* VBOX_API_VERSION >= 4000000 */
-
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("could not attach shared folder '%s', rc=%08x"),
-                                       dev->data.fs->dst, (unsigned)rc);
-                    } else {
-                        ret = 0;
-                    }
-
-                    VBOX_UTF16_FREE(nameUtf16);
-                    VBOX_UTF16_FREE(hostPathUtf16);
-                }
-                machine->vtbl->SaveSettings(machine);
-                VBOX_RELEASE(machine);
-            }
-            VBOX_SESSION_CLOSE();
-        }
-    }
-
- cleanup:
-    vboxIIDUnalloc(&iid);
-    virDomainDefFree(def);
-    virDomainDeviceDefFree(dev);
-    return ret;
-}
-
-static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml)
-{
-    return vboxDomainAttachDeviceImpl(dom, xml, 0);
-}
-
-static int
-vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
-                            unsigned int flags)
-{
-    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
-    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot modify the persistent configuration of a domain"));
-        return -1;
-    }
-
-    return vboxDomainAttachDeviceImpl(dom, xml, 0);
-}
-
-static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
-                                       unsigned int flags)
-{
-    virCheckFlags(VIR_DOMAIN_AFFECT_CURRENT |
-                  VIR_DOMAIN_AFFECT_LIVE |
-                  VIR_DOMAIN_AFFECT_CONFIG, -1);
-
-    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot modify the persistent configuration of a domain"));
-        return -1;
-    }
-
-    return vboxDomainAttachDeviceImpl(dom, xml, 1);
-}
-
-static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml)
-{
-    VBOX_OBJECT_CHECK(dom->conn, int, -1);
-    IMachine *machine    = NULL;
-    vboxIID iid = VBOX_IID_INITIALIZER;
-    PRUint32 state       = MachineState_Null;
-    virDomainDefPtr def  = NULL;
-    virDomainDeviceDefPtr dev  = NULL;
-    nsresult rc;
-
-    if (VIR_ALLOC(def) < 0)
-        return ret;
-
-    if (VIR_STRDUP(def->os.type, "hvm") < 0)
-        goto cleanup;
-
-    dev = virDomainDeviceDefParse(xml, def, data->caps, data->xmlopt,
-                                  VIR_DOMAIN_XML_INACTIVE);
-    if (dev == NULL)
-        goto cleanup;
-
-    vboxIIDFromUUID(&iid, dom->uuid);
-    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_NO_DOMAIN, "%s",
-                       _("no domain with matching uuid"));
-        goto cleanup;
-    }
-
-    if (machine) {
-        machine->vtbl->GetState(machine, &state);
-
-        if ((state == MachineState_Running) ||
-            (state == MachineState_Paused)) {
-            rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
-        } else {
-            rc = VBOX_SESSION_OPEN(iid.value, machine);
-        }
-
-        if (NS_SUCCEEDED(rc)) {
-            rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
-            if (NS_SUCCEEDED(rc) && machine) {
-                if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
-#if VBOX_API_VERSION < 3001000
-                    int type = virDomainDiskGetType(dev->data.disk);
-
-                    if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
-                        if (type == VIR_STORAGE_TYPE_FILE) {
-                            IDVDDrive *dvdDrive = NULL;
-                            /* Currently CDROM/DVD Drive is always IDE
-                             * Secondary Master so neglecting the following
-                             * parameter dev->data.disk->bus
-                             */
-                            machine->vtbl->GetDVDDrive(machine, &dvdDrive);
-                            if (dvdDrive) {
-                                rc = dvdDrive->vtbl->Unmount(dvdDrive);
-                                if (NS_FAILED(rc)) {
-                                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                   _("could not de-attach the mounted ISO, rc=%08x"),
-                                                   (unsigned)rc);
-                                } else {
-                                    ret = 0;
-                                }
-                                VBOX_RELEASE(dvdDrive);
-                            }
-                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
-                        }
-                    } else if (dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
-                        if (type == VIR_STORAGE_TYPE_FILE) {
-                            IFloppyDrive *floppyDrive;
-                            machine->vtbl->GetFloppyDrive(machine, &floppyDrive);
-                            if (floppyDrive) {
-                                PRBool enabled = PR_FALSE;
-
-                                floppyDrive->vtbl->GetEnabled(floppyDrive, &enabled);
-                                if (enabled) {
-                                    rc = floppyDrive->vtbl->Unmount(floppyDrive);
-                                    if (NS_FAILED(rc)) {
-                                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                                       _("could not attach the file "
-                                                         "to floppy drive, rc=%08x"),
-                                                       (unsigned)rc);
-                                    } else {
-                                        ret = 0;
-                                    }
-                                } else {
-                                    /* If you are here means floppy drive is already unmounted
-                                     * so don't flag error, just say everything is fine and quit
-                                     */
-                                    ret = 0;
-                                }
-                                VBOX_RELEASE(floppyDrive);
-                            }
-                        } else if (type == VIR_STORAGE_TYPE_BLOCK) {
-                        }
-                    }
-#else  /* VBOX_API_VERSION >= 3001000 */
-#endif /* VBOX_API_VERSION >= 3001000 */
-                } else if (dev->type == VIR_DOMAIN_DEVICE_NET) {
-                } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
-                    if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
-                        if (dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
-                        }
-                    }
-                } else if (dev->type == VIR_DOMAIN_DEVICE_FS &&
-                           dev->data.fs->type == VIR_DOMAIN_FS_TYPE_MOUNT) {
-                    PRUnichar *nameUtf16;
-
-                    VBOX_UTF8_TO_UTF16(dev->data.fs->dst, &nameUtf16);
-
-                    rc = machine->vtbl->RemoveSharedFolder(machine, nameUtf16);
-
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR,
-                                       _("could not detach shared folder '%s', rc=%08x"),
-                                       dev->data.fs->dst, (unsigned)rc);
-                    } else {
-                        ret = 0;
-                    }
-
-                    VBOX_UTF16_FREE(nameUtf16);
-                }
-                machine->vtbl->SaveSettings(machine);
-                VBOX_RELEASE(machine);
-            }
-            VBOX_SESSION_CLOSE();
-        }
-    }
-
- cleanup:
-    vboxIIDUnalloc(&iid);
-    virDomainDefFree(def);
-    virDomainDeviceDefFree(dev);
-    return ret;
-}
-
-static int
-vboxDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
-                            unsigned int flags)
-{
-    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1);
-
-    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
-        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
-                       _("cannot modify the persistent configuration of a domain"));
-        return -1;
-    }
-
-    return vboxDomainDetachDevice(dom, xml);
-}
-
-static int
-vboxDomainSnapshotGetAll(virDomainPtr dom,
-                         IMachine *machine,
-                         ISnapshot ***snapshots)
-{
-    vboxIID empty = VBOX_IID_INITIALIZER;
-    ISnapshot **list = NULL;
-    PRUint32 count;
-    nsresult rc;
-    unsigned int next;
-    unsigned int top;
-
-    rc = machine->vtbl->GetSnapshotCount(machine, &count);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not get snapshot count for domain %s"),
-                       dom->name);
-        goto error;
-    }
-
-    if (count == 0)
-        goto out;
-
-    if (VIR_ALLOC_N(list, count) < 0)
-        goto error;
-
-#if VBOX_API_VERSION < 4000000
-    rc = machine->vtbl->GetSnapshot(machine, empty.value, list);
-#else /* VBOX_API_VERSION >= 4000000 */
-    rc = machine->vtbl->FindSnapshot(machine, empty.value, list);
-#endif /* VBOX_API_VERSION >= 4000000 */
-    if (NS_FAILED(rc) || !list[0]) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("could not get root snapshot for domain %s"),
-                       dom->name);
-        goto error;
-    }
-
-    /* BFS walk through snapshot tree */
-    top = 1;
-    for (next = 0; next < count; next++) {
-        vboxArray children = VBOX_ARRAY_INITIALIZER;
-        size_t i;
-
-        if (!list[next]) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("unexpected number of snapshots < %u"), count);
-            goto error;
-        }
-
-        rc = vboxArrayGet(&children, list[next],
-                               list[next]->vtbl->GetChildren);
-        if (NS_FAILED(rc)) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           "%s", _("could not get children snapshots"));
-            goto error;
-        }
-        for (i = 0; i < children.count; i++) {
-            ISnapshot *child = children.items[i];
-            if (!child)
-                continue;
-            if (top == count) {
-                virReportError(VIR_ERR_INTERNAL_ERROR,
-                               _("unexpected number of snapshots > %u"), count);
-                vboxArrayRelease(&children);
-                goto error;
-            }
-            VBOX_ADDREF(child);
-            list[top++] = child;
-        }
-        vboxArrayRelease(&children);
-    }
-
- out:
-    *snapshots = list;
-    return count;
-
- error:
-    if (list) {
-        for (next = 0; next < count; next++)
-            VBOX_RELEASE(list[next]);
-    }
-    VIR_FREE(list);
-
-    return -1;
-}
-
-static ISnapshot *
-vboxDomainSnapshotGet(vboxGlobalData *data,
-                      virDomainPtr dom,
-                      IMachine *machine,
-                      const char *name)
-{
-    ISnapshot **snapshots = NULL;
-    ISnapshot *snapshot = NULL;
-    nsresult rc;
-    int count = 0;
-    size_t i;
+    ISnapshot **snapshots = NULL;
+    ISnapshot *snapshot = NULL;
+    nsresult rc;
+    int count = 0;
+    size_t i;
 
     if ((count = vboxDomainSnapshotGetAll(dom, machine, &snapshots)) < 0)
         goto cleanup;
@@ -9801,22 +8820,265 @@ vboxStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
     return ret;
 }
 
-static virStorageVolPtr
-vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
+static virStorageVolPtr
+vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
+{
+    VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
+    vboxIID hddIID = VBOX_IID_INITIALIZER;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    IHardDisk *hardDisk  = NULL;
+    nsresult rc;
+
+    if (!key)
+        return ret;
+
+    if (virUUIDParse(key, uuid) < 0) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Could not parse UUID from '%s'"), key);
+        return NULL;
+    }
+
+    vboxIIDFromUUID(&hddIID, uuid);
+#if VBOX_API_VERSION < 4000000
+    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
+#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
+    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
+                                         DeviceType_HardDisk, &hardDisk);
+#else
+    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
+                                         DeviceType_HardDisk, AccessMode_ReadWrite,
+                                         PR_FALSE, &hardDisk);
+#endif /* VBOX_API_VERSION >= 4000000 */
+    if (NS_SUCCEEDED(rc)) {
+        PRUint32 hddstate;
+
+        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
+        if (hddstate != MediaState_Inaccessible) {
+            PRUnichar *hddNameUtf16 = NULL;
+            char      *hddNameUtf8  = NULL;
+
+            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
+            VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
+
+            if (hddNameUtf8) {
+                if (vboxConnectNumOfStoragePools(conn) == 1) {
+                    ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
+                                           NULL, NULL);
+                    VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
+                } else {
+                    /* TODO: currently only one default pool and thus
+                     * nothing here, change it when pools are supported
+                     */
+                }
+
+                VIR_DEBUG("Storage Volume Name: %s", key);
+                VIR_DEBUG("Storage Volume key : %s", hddNameUtf8);
+
+                VBOX_UTF8_FREE(hddNameUtf8);
+                VBOX_UTF16_FREE(hddNameUtf16);
+            }
+        }
+
+        VBOX_MEDIUM_RELEASE(hardDisk);
+    }
+
+    vboxIIDUnalloc(&hddIID);
+    return ret;
+}
+
+static virStorageVolPtr
+vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
+{
+    VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
+    PRUnichar *hddPathUtf16 = NULL;
+    IHardDisk *hardDisk     = NULL;
+    nsresult rc;
+
+    if (!path)
+        return ret;
+
+    VBOX_UTF8_TO_UTF16(path, &hddPathUtf16);
+
+    if (!hddPathUtf16)
+        return ret;
+
+#if VBOX_API_VERSION < 4000000
+    rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk);
+#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
+    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16,
+                                         DeviceType_HardDisk, &hardDisk);
+#else
+    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16,
+                                         DeviceType_HardDisk, AccessMode_ReadWrite,
+                                         PR_FALSE, &hardDisk);
+#endif /* VBOX_API_VERSION >= 4000000 */
+    if (NS_SUCCEEDED(rc)) {
+        PRUint32 hddstate;
+
+        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
+        if (hddstate != MediaState_Inaccessible) {
+            PRUnichar *hddNameUtf16 = NULL;
+            char      *hddNameUtf8  = NULL;
+
+            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
+
+            if (hddNameUtf16) {
+                VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
+                VBOX_UTF16_FREE(hddNameUtf16);
+            }
+
+            if (hddNameUtf8) {
+                vboxIID hddIID = VBOX_IID_INITIALIZER;
+                unsigned char uuid[VIR_UUID_BUFLEN];
+                char key[VIR_UUID_STRING_BUFLEN] = "";
+
+                rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
+                if (NS_SUCCEEDED(rc)) {
+                    vboxIIDToUUID(&hddIID, uuid);
+                    virUUIDFormat(uuid, key);
+
+                    /* TODO: currently only one default pool and thus
+                     * the check below, change it when pools are supported
+                     */
+                    if (vboxConnectNumOfStoragePools(conn) == 1)
+                        ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
+                                               NULL, NULL);
+
+                    VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
+                    VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
+                    VIR_DEBUG("Storage Volume key : %s", key);
+                }
+
+                vboxIIDUnalloc(&hddIID);
+            }
+
+            VBOX_UTF8_FREE(hddNameUtf8);
+        }
+
+        VBOX_MEDIUM_RELEASE(hardDisk);
+    }
+
+    VBOX_UTF16_FREE(hddPathUtf16);
+
+    return ret;
+}
+
+static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
+                                                const char *xml,
+                                                unsigned int flags)
+{
+    VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL);
+    virStorageVolDefPtr  def  = NULL;
+    PRUnichar *hddFormatUtf16 = NULL;
+    PRUnichar *hddNameUtf16   = NULL;
+    virStoragePoolDef poolDef;
+    nsresult rc;
+
+    virCheckFlags(0, NULL);
+
+    /* since there is currently one default pool now
+     * and virStorageVolDefFormat() just checks it type
+     * so just assign it for now, change the behaviour
+     * when vbox supports pools.
+     */
+    memset(&poolDef, 0, sizeof(poolDef));
+    poolDef.type = VIR_STORAGE_POOL_DIR;
+
+    if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL)
+        goto cleanup;
+
+    if (!def->name ||
+        (def->type != VIR_STORAGE_VOL_FILE))
+        goto cleanup;
+
+    /* For now only the vmdk, vpc and vdi type harddisk
+     * variants can be created.  For historical reason, we default to vdi */
+    if (def->target.format == VIR_STORAGE_FILE_VMDK) {
+        VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
+    } else if (def->target.format == VIR_STORAGE_FILE_VPC) {
+        VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
+    } else {
+        VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
+    }
+
+    VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16);
+
+    if (hddFormatUtf16 && hddNameUtf16) {
+        IHardDisk *hardDisk = NULL;
+
+        rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
+        if (NS_SUCCEEDED(rc)) {
+            IProgress *progress    = NULL;
+            PRUint64   logicalSize = VIR_DIV_UP(def->target.capacity,
+                                                1024 * 1024);
+            PRUint32   variant     = HardDiskVariant_Standard;
+
+            if (def->target.capacity == def->target.allocation)
+                variant = HardDiskVariant_Fixed;
+
+#if VBOX_API_VERSION < 4003000
+            rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
+#else
+            rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress);
+#endif
+            if (NS_SUCCEEDED(rc) && progress) {
+#if VBOX_API_VERSION == 2002000
+                nsresult resultCode;
+#else
+                PRInt32  resultCode;
+#endif
+
+                progress->vtbl->WaitForCompletion(progress, -1);
+                progress->vtbl->GetResultCode(progress, &resultCode);
+
+                if (NS_SUCCEEDED(resultCode)) {
+                    vboxIID hddIID = VBOX_IID_INITIALIZER;
+                    unsigned char uuid[VIR_UUID_BUFLEN];
+                    char key[VIR_UUID_STRING_BUFLEN] = "";
+
+                    rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
+                    if (NS_SUCCEEDED(rc)) {
+                        vboxIIDToUUID(&hddIID, uuid);
+                        virUUIDFormat(uuid, key);
+
+                        ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
+                                               NULL, NULL);
+                    }
+
+                    vboxIIDUnalloc(&hddIID);
+                }
+
+                VBOX_RELEASE(progress);
+            }
+        }
+    }
+
+    VBOX_UTF16_FREE(hddFormatUtf16);
+    VBOX_UTF16_FREE(hddNameUtf16);
+
+ cleanup:
+    virStorageVolDefFree(def);
+    return ret;
+}
+
+static int vboxStorageVolDelete(virStorageVolPtr vol,
+                                unsigned int flags)
 {
-    VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
+    VBOX_OBJECT_CHECK(vol->conn, int, -1);
     vboxIID hddIID = VBOX_IID_INITIALIZER;
     unsigned char uuid[VIR_UUID_BUFLEN];
     IHardDisk *hardDisk  = NULL;
+    int deregister = 0;
     nsresult rc;
+    size_t i = 0;
+    size_t j = 0;
 
-    if (!key)
-        return ret;
+    virCheckFlags(0, -1);
 
-    if (virUUIDParse(key, uuid) < 0) {
+    if (virUUIDParse(vol->key, uuid) < 0) {
         virReportError(VIR_ERR_INVALID_ARG,
-                       _("Could not parse UUID from '%s'"), key);
-        return NULL;
+                       _("Could not parse UUID from '%s'"), vol->key);
+        return -1;
     }
 
     vboxIIDFromUUID(&hddIID, uuid);
@@ -9835,28 +9097,134 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
 
         VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
         if (hddstate != MediaState_Inaccessible) {
-            PRUnichar *hddNameUtf16 = NULL;
-            char      *hddNameUtf8  = NULL;
+            PRUint32  machineIdsSize = 0;
+            vboxArray machineIds = VBOX_ARRAY_INITIALIZER;
 
-            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
-            VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
+#if VBOX_API_VERSION < 3001000
+            vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds);
+#else  /* VBOX_API_VERSION >= 3001000 */
+            vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds);
+#endif /* VBOX_API_VERSION >= 3001000 */
 
-            if (hddNameUtf8) {
-                if (vboxConnectNumOfStoragePools(conn) == 1) {
-                    ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
-                                           NULL, NULL);
-                    VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
-                } else {
-                    /* TODO: currently only one default pool and thus
-                     * nothing here, change it when pools are supported
-                     */
+#if VBOX_API_VERSION == 2002000 && defined WIN32
+            /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the
+             * machineIds array contains direct instances of the GUID struct
+             * instead of pointers to the actual struct instances. But there
+             * is no 128bit width simple item type for a SafeArray to fit a
+             * GUID in. The largest simple type it 64bit width and VirtualBox
+             * uses two of this 64bit items to represents one GUID. Therefore,
+             * we divide the size of the SafeArray by two, to compensate for
+             * this workaround in VirtualBox */
+            machineIds.count /= 2;
+#endif /* VBOX_API_VERSION >= 2002000 */
+
+            machineIdsSize = machineIds.count;
+
+            for (i = 0; i < machineIds.count; i++) {
+                IMachine *machine = NULL;
+                vboxIID machineId = VBOX_IID_INITIALIZER;
+
+                vboxIIDFromArrayItem(&machineId, &machineIds, i);
+
+#if VBOX_API_VERSION >= 4000000
+                rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine);
+                if (NS_FAILED(rc)) {
+                    virReportError(VIR_ERR_NO_DOMAIN, "%s",
+                                   _("no domain with matching uuid"));
+                    break;
                 }
+#endif
 
-                VIR_DEBUG("Storage Volume Name: %s", key);
-                VIR_DEBUG("Storage Volume key : %s", hddNameUtf8);
+                rc = VBOX_SESSION_OPEN(machineId.value, machine);
 
-                VBOX_UTF8_FREE(hddNameUtf8);
-                VBOX_UTF16_FREE(hddNameUtf16);
+                if (NS_SUCCEEDED(rc)) {
+
+                    rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
+                    if (NS_SUCCEEDED(rc)) {
+                        vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER;
+
+#if VBOX_API_VERSION < 3001000
+                        vboxArrayGet(&hddAttachments, machine,
+                                     machine->vtbl->GetHardDiskAttachments);
+#else  /* VBOX_API_VERSION >= 3001000 */
+                        vboxArrayGet(&hddAttachments, machine,
+                                     machine->vtbl->GetMediumAttachments);
+#endif /* VBOX_API_VERSION >= 3001000 */
+                        for (j = 0; j < hddAttachments.count; j++) {
+                            IHardDiskAttachment *hddAttachment = hddAttachments.items[j];
+
+                            if (hddAttachment) {
+                                IHardDisk *hdd = NULL;
+
+#if VBOX_API_VERSION < 3001000
+                                rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd);
+#else  /* VBOX_API_VERSION >= 3001000 */
+                                rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd);
+#endif /* VBOX_API_VERSION >= 3001000 */
+                                if (NS_SUCCEEDED(rc) && hdd) {
+                                    vboxIID iid = VBOX_IID_INITIALIZER;
+
+                                    rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value);
+                                    if (NS_SUCCEEDED(rc)) {
+
+                                            DEBUGIID("HardDisk (to delete) UUID", hddIID.value);
+                                            DEBUGIID("HardDisk (currently processing) UUID", iid.value);
+
+                                        if (vboxIIDIsEqual(&hddIID, &iid)) {
+                                            PRUnichar *controller = NULL;
+                                            PRInt32    port       = 0;
+                                            PRInt32    device     = 0;
+
+                                            DEBUGIID("Found HardDisk to delete, UUID", hddIID.value);
+
+                                            hddAttachment->vtbl->GetController(hddAttachment, &controller);
+                                            hddAttachment->vtbl->GetPort(hddAttachment, &port);
+                                            hddAttachment->vtbl->GetDevice(hddAttachment, &device);
+
+#if VBOX_API_VERSION < 3001000
+                                            rc = machine->vtbl->DetachHardDisk(machine, controller, port, device);
+#else  /* VBOX_API_VERSION >= 3001000 */
+                                            rc = machine->vtbl->DetachDevice(machine, controller, port, device);
+#endif /* VBOX_API_VERSION >= 3001000 */
+                                            if (NS_SUCCEEDED(rc)) {
+                                                rc = machine->vtbl->SaveSettings(machine);
+                                                VIR_DEBUG("saving machine settings");
+                                            }
+
+                                            if (NS_SUCCEEDED(rc)) {
+                                                deregister++;
+                                                VIR_DEBUG("deregistering hdd:%d", deregister);
+                                            }
+
+                                            VBOX_UTF16_FREE(controller);
+                                        }
+                                        vboxIIDUnalloc(&iid);
+                                    }
+                                    VBOX_MEDIUM_RELEASE(hdd);
+                                }
+                            }
+                        }
+                        vboxArrayRelease(&hddAttachments);
+                        VBOX_RELEASE(machine);
+                    }
+                    VBOX_SESSION_CLOSE();
+                }
+
+                vboxIIDUnalloc(&machineId);
+            }
+
+            vboxArrayUnalloc(&machineIds);
+
+            if (machineIdsSize == 0 || machineIdsSize == deregister) {
+                IProgress *progress = NULL;
+                rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress);
+
+                if (NS_SUCCEEDED(rc) && progress) {
+                    progress->vtbl->WaitForCompletion(progress, -1);
+                    VBOX_RELEASE(progress);
+                    DEBUGIID("HardDisk deleted, UUID", hddIID.value);
+                    ret = 0;
+                }
             }
         }
 
@@ -9864,32 +9232,36 @@ vboxStorageVolLookupByKey(virConnectPtr conn, const char *key)
     }
 
     vboxIIDUnalloc(&hddIID);
+
     return ret;
 }
 
-static virStorageVolPtr
-vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
+static int
+vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
 {
-    VBOX_OBJECT_CHECK(conn, virStorageVolPtr, NULL);
-    PRUnichar *hddPathUtf16 = NULL;
-    IHardDisk *hardDisk     = NULL;
+    VBOX_OBJECT_CHECK(vol->conn, int, -1);
+    IHardDisk *hardDisk  = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    vboxIID hddIID = VBOX_IID_INITIALIZER;
     nsresult rc;
 
-    if (!path)
+    if (!info)
         return ret;
 
-    VBOX_UTF8_TO_UTF16(path, &hddPathUtf16);
-
-    if (!hddPathUtf16)
+    if (virUUIDParse(vol->key, uuid) < 0) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Could not parse UUID from '%s'"), vol->key);
         return ret;
+    }
 
+    vboxIIDFromUUID(&hddIID, uuid);
 #if VBOX_API_VERSION < 4000000
-    rc = data->vboxObj->vtbl->FindHardDisk(data->vboxObj, hddPathUtf16, &hardDisk);
+    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
 #elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddPathUtf16,
+    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
                                          DeviceType_HardDisk, &hardDisk);
 #else
-    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddPathUtf16,
+    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
                                          DeviceType_HardDisk, AccessMode_ReadWrite,
                                          PR_FALSE, &hardDisk);
 #endif /* VBOX_API_VERSION >= 4000000 */
@@ -9898,168 +9270,169 @@ vboxStorageVolLookupByPath(virConnectPtr conn, const char *path)
 
         VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
         if (hddstate != MediaState_Inaccessible) {
-            PRUnichar *hddNameUtf16 = NULL;
-            char      *hddNameUtf8  = NULL;
-
-            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetName, &hddNameUtf16);
-
-            if (hddNameUtf16) {
-                VBOX_UTF16_TO_UTF8(hddNameUtf16, &hddNameUtf8);
-                VBOX_UTF16_FREE(hddNameUtf16);
-            }
-
-            if (hddNameUtf8) {
-                vboxIID hddIID = VBOX_IID_INITIALIZER;
-                unsigned char uuid[VIR_UUID_BUFLEN];
-                char key[VIR_UUID_STRING_BUFLEN] = "";
+#if VBOX_API_VERSION < 4000000
+            PRUint64 hddLogicalSize;
+            PRUint64 hddActualSize;
+#else /* VBOX_API_VERSION >= 4000000 */
+            PRInt64 hddLogicalSize;
+            PRInt64 hddActualSize;
+#endif /* VBOX_API_VERSION >= 4000000 */
 
-                rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
-                if (NS_SUCCEEDED(rc)) {
-                    vboxIIDToUUID(&hddIID, uuid);
-                    virUUIDFormat(uuid, key);
+            info->type = VIR_STORAGE_VOL_FILE;
 
-                    /* TODO: currently only one default pool and thus
-                     * the check below, change it when pools are supported
-                     */
-                    if (vboxConnectNumOfStoragePools(conn) == 1)
-                        ret = virGetStorageVol(conn, "default-pool", hddNameUtf8, key,
-                                               NULL, NULL);
+            hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
+#if VBOX_API_VERSION < 4000000
+            info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
+#else /* VBOX_API_VERSION >= 4000000 */
+            info->capacity = hddLogicalSize;
+#endif /* VBOX_API_VERSION >= 4000000 */
 
-                    VIR_DEBUG("Storage Volume Pool: %s", "default-pool");
-                    VIR_DEBUG("Storage Volume Name: %s", hddNameUtf8);
-                    VIR_DEBUG("Storage Volume key : %s", key);
-                }
+            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
+            info->allocation = hddActualSize;
 
-                vboxIIDUnalloc(&hddIID);
-            }
+            ret = 0;
 
-            VBOX_UTF8_FREE(hddNameUtf8);
+            VIR_DEBUG("Storage Volume Name: %s", vol->name);
+            VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File");
+            VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity);
+            VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation);
         }
 
         VBOX_MEDIUM_RELEASE(hardDisk);
     }
 
-    VBOX_UTF16_FREE(hddPathUtf16);
+    vboxIIDUnalloc(&hddIID);
 
     return ret;
 }
 
-static virStorageVolPtr vboxStorageVolCreateXML(virStoragePoolPtr pool,
-                                                const char *xml,
-                                                unsigned int flags)
+static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
 {
-    VBOX_OBJECT_CHECK(pool->conn, virStorageVolPtr, NULL);
-    virStorageVolDefPtr  def  = NULL;
-    PRUnichar *hddFormatUtf16 = NULL;
-    PRUnichar *hddNameUtf16   = NULL;
-    virStoragePoolDef poolDef;
+    VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
+    IHardDisk *hardDisk  = NULL;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    vboxIID hddIID = VBOX_IID_INITIALIZER;
+    virStoragePoolDef pool;
+    virStorageVolDef def;
+    int defOk = 0;
     nsresult rc;
 
     virCheckFlags(0, NULL);
 
-    /* since there is currently one default pool now
-     * and virStorageVolDefFormat() just checks it type
-     * so just assign it for now, change the behaviour
-     * when vbox supports pools.
-     */
-    memset(&poolDef, 0, sizeof(poolDef));
-    poolDef.type = VIR_STORAGE_POOL_DIR;
+    memset(&pool, 0, sizeof(pool));
+    memset(&def, 0, sizeof(def));
 
-    if ((def = virStorageVolDefParseString(&poolDef, xml)) == NULL)
-        goto cleanup;
+    if (virUUIDParse(vol->key, uuid) < 0) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Could not parse UUID from '%s'"), vol->key);
+        return ret;
+    }
 
-    if (!def->name ||
-        (def->type != VIR_STORAGE_VOL_FILE))
-        goto cleanup;
+    vboxIIDFromUUID(&hddIID, uuid);
+#if VBOX_API_VERSION < 4000000
+    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
+#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
+    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
+                                         DeviceType_HardDisk, &hardDisk);
+#else
+    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
+                                         DeviceType_HardDisk, AccessMode_ReadWrite,
+                                         PR_FALSE, &hardDisk);
+#endif /* VBOX_API_VERSION >= 4000000 */
+    if (NS_SUCCEEDED(rc)) {
+        PRUint32 hddstate;
 
-    /* For now only the vmdk, vpc and vdi type harddisk
-     * variants can be created.  For historical reason, we default to vdi */
-    if (def->target.format == VIR_STORAGE_FILE_VMDK) {
-        VBOX_UTF8_TO_UTF16("VMDK", &hddFormatUtf16);
-    } else if (def->target.format == VIR_STORAGE_FILE_VPC) {
-        VBOX_UTF8_TO_UTF16("VHD", &hddFormatUtf16);
-    } else {
-        VBOX_UTF8_TO_UTF16("VDI", &hddFormatUtf16);
-    }
+        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
+        if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) {
+            PRUnichar *hddFormatUtf16 = NULL;
+#if VBOX_API_VERSION < 4000000
+            PRUint64 hddLogicalSize;
+            PRUint64 hddActualSize;
+#else /* VBOX_API_VERSION >= 4000000 */
+            PRInt64 hddLogicalSize;
+            PRInt64 hddActualSize;
+#endif /* VBOX_API_VERSION >= 4000000 */
 
-    VBOX_UTF8_TO_UTF16(def->name, &hddNameUtf16);
+            /* since there is currently one default pool now
+             * and virStorageVolDefFormat() just checks it type
+             * so just assign it for now, change the behaviour
+             * when vbox supports pools.
+             */
+            pool.type = VIR_STORAGE_POOL_DIR;
+            def.type = VIR_STORAGE_VOL_FILE;
+            defOk = 1;
 
-    if (hddFormatUtf16 && hddNameUtf16) {
-        IHardDisk *hardDisk = NULL;
+            rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
+            if (NS_SUCCEEDED(rc) && defOk) {
+#if VBOX_API_VERSION < 4000000
+                def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
+#else /* VBOX_API_VERSION >= 4000000 */
+                def.target.capacity = hddLogicalSize;
+#endif /* VBOX_API_VERSION >= 4000000 */
+            } else
+                defOk = 0;
 
-        rc = data->vboxObj->vtbl->CreateHardDisk(data->vboxObj, hddFormatUtf16, hddNameUtf16, &hardDisk);
-        if (NS_SUCCEEDED(rc)) {
-            IProgress *progress    = NULL;
-            PRUint64   logicalSize = VIR_DIV_UP(def->target.capacity,
-                                                1024 * 1024);
-            PRUint32   variant     = HardDiskVariant_Standard;
+            rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
+            if (NS_SUCCEEDED(rc) && defOk)
+                def.target.allocation = hddActualSize;
+            else
+                defOk = 0;
 
-            if (def->target.capacity == def->target.allocation)
-                variant = HardDiskVariant_Fixed;
+            if (VIR_STRDUP(def.name, vol->name) < 0)
+                defOk = 0;
 
-#if VBOX_API_VERSION < 4003000
-            rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, variant, &progress);
-#else
-            rc = hardDisk->vtbl->CreateBaseStorage(hardDisk, logicalSize, 1, &variant, &progress);
-#endif
-            if (NS_SUCCEEDED(rc) && progress) {
-#if VBOX_API_VERSION == 2002000
-                nsresult resultCode;
-#else
-                PRInt32  resultCode;
-#endif
+            if (VIR_STRDUP(def.key, vol->key) < 0)
+                defOk = 0;
 
-                progress->vtbl->WaitForCompletion(progress, -1);
-                progress->vtbl->GetResultCode(progress, &resultCode);
+            rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16);
+            if (NS_SUCCEEDED(rc) && defOk) {
+                char *hddFormatUtf8 = NULL;
 
-                if (NS_SUCCEEDED(resultCode)) {
-                    vboxIID hddIID = VBOX_IID_INITIALIZER;
-                    unsigned char uuid[VIR_UUID_BUFLEN];
-                    char key[VIR_UUID_STRING_BUFLEN] = "";
+                VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8);
+                if (hddFormatUtf8) {
 
-                    rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetId, &hddIID.value);
-                    if (NS_SUCCEEDED(rc)) {
-                        vboxIIDToUUID(&hddIID, uuid);
-                        virUUIDFormat(uuid, key);
+                    VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8);
 
-                        ret = virGetStorageVol(pool->conn, pool->name, def->name, key,
-                                               NULL, NULL);
-                    }
+                    if (STRCASEEQ("vmdk", hddFormatUtf8))
+                        def.target.format = VIR_STORAGE_FILE_VMDK;
+                    else if (STRCASEEQ("vhd", hddFormatUtf8))
+                        def.target.format = VIR_STORAGE_FILE_VPC;
+                    else if (STRCASEEQ("vdi", hddFormatUtf8))
+                        def.target.format = VIR_STORAGE_FILE_VDI;
+                    else
+                        def.target.format = VIR_STORAGE_FILE_RAW;
 
-                    vboxIIDUnalloc(&hddIID);
+                    VBOX_UTF8_FREE(hddFormatUtf8);
                 }
 
-                VBOX_RELEASE(progress);
+                VBOX_UTF16_FREE(hddFormatUtf16);
+            } else {
+                defOk = 0;
             }
         }
+
+        VBOX_MEDIUM_RELEASE(hardDisk);
     }
 
-    VBOX_UTF16_FREE(hddFormatUtf16);
-    VBOX_UTF16_FREE(hddNameUtf16);
+    vboxIIDUnalloc(&hddIID);
+
+    if (defOk)
+        ret = virStorageVolDefFormat(&pool, &def);
 
- cleanup:
-    virStorageVolDefFree(def);
     return ret;
 }
 
-static int vboxStorageVolDelete(virStorageVolPtr vol,
-                                unsigned int flags)
-{
-    VBOX_OBJECT_CHECK(vol->conn, int, -1);
-    vboxIID hddIID = VBOX_IID_INITIALIZER;
-    unsigned char uuid[VIR_UUID_BUFLEN];
+static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
+    VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
     IHardDisk *hardDisk  = NULL;
-    int deregister = 0;
+    unsigned char uuid[VIR_UUID_BUFLEN];
+    vboxIID hddIID = VBOX_IID_INITIALIZER;
     nsresult rc;
-    size_t i = 0;
-    size_t j = 0;
-
-    virCheckFlags(0, -1);
 
     if (virUUIDParse(vol->key, uuid) < 0) {
         virReportError(VIR_ERR_INVALID_ARG,
                        _("Could not parse UUID from '%s'"), vol->key);
-        return -1;
+        return ret;
     }
 
     vboxIIDFromUUID(&hddIID, uuid);
@@ -10078,1123 +9451,1437 @@ static int vboxStorageVolDelete(virStorageVolPtr vol,
 
         VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
         if (hddstate != MediaState_Inaccessible) {
-            PRUint32  machineIdsSize = 0;
-            vboxArray machineIds = VBOX_ARRAY_INITIALIZER;
+            PRUnichar *hddLocationUtf16 = NULL;
+            char      *hddLocationUtf8  = NULL;
 
-#if VBOX_API_VERSION < 3001000
-            vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->imedium.GetMachineIds);
-#else  /* VBOX_API_VERSION >= 3001000 */
-            vboxArrayGet(&machineIds, hardDisk, hardDisk->vtbl->GetMachineIds);
-#endif /* VBOX_API_VERSION >= 3001000 */
+            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16);
 
-#if VBOX_API_VERSION == 2002000 && defined WIN32
-            /* VirtualBox 2.2 on Windows represents IIDs as GUIDs and the
-             * machineIds array contains direct instances of the GUID struct
-             * instead of pointers to the actual struct instances. But there
-             * is no 128bit width simple item type for a SafeArray to fit a
-             * GUID in. The largest simple type it 64bit width and VirtualBox
-             * uses two of this 64bit items to represents one GUID. Therefore,
-             * we divide the size of the SafeArray by two, to compensate for
-             * this workaround in VirtualBox */
-            machineIds.count /= 2;
-#endif /* VBOX_API_VERSION >= 2002000 */
+            VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8);
+            if (hddLocationUtf8) {
 
-            machineIdsSize = machineIds.count;
+                ignore_value(VIR_STRDUP(ret, hddLocationUtf8));
 
-            for (i = 0; i < machineIds.count; i++) {
-                IMachine *machine = NULL;
-                vboxIID machineId = VBOX_IID_INITIALIZER;
+                VIR_DEBUG("Storage Volume Name: %s", vol->name);
+                VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8);
+                VIR_DEBUG("Storage Volume Pool: %s", vol->pool);
 
-                vboxIIDFromArrayItem(&machineId, &machineIds, i);
+                VBOX_UTF8_FREE(hddLocationUtf8);
+            }
 
-#if VBOX_API_VERSION >= 4000000
-                rc = VBOX_OBJECT_GET_MACHINE(machineId.value, &machine);
-                if (NS_FAILED(rc)) {
-                    virReportError(VIR_ERR_NO_DOMAIN, "%s",
-                                   _("no domain with matching uuid"));
-                    break;
-                }
-#endif
+            VBOX_UTF16_FREE(hddLocationUtf16);
+        }
 
-                rc = VBOX_SESSION_OPEN(machineId.value, machine);
+        VBOX_MEDIUM_RELEASE(hardDisk);
+    }
 
-                if (NS_SUCCEEDED(rc)) {
+    vboxIIDUnalloc(&hddIID);
 
-                    rc = data->vboxSession->vtbl->GetMachine(data->vboxSession, &machine);
-                    if (NS_SUCCEEDED(rc)) {
-                        vboxArray hddAttachments = VBOX_ARRAY_INITIALIZER;
+    return ret;
+}
 
-#if VBOX_API_VERSION < 3001000
-                        vboxArrayGet(&hddAttachments, machine,
-                                     machine->vtbl->GetHardDiskAttachments);
-#else  /* VBOX_API_VERSION >= 3001000 */
-                        vboxArrayGet(&hddAttachments, machine,
-                                     machine->vtbl->GetMediumAttachments);
-#endif /* VBOX_API_VERSION >= 3001000 */
-                        for (j = 0; j < hddAttachments.count; j++) {
-                            IHardDiskAttachment *hddAttachment = hddAttachments.items[j];
+#if VBOX_API_VERSION >= 4000000
+static char *
+vboxDomainScreenshot(virDomainPtr dom,
+                     virStreamPtr st,
+                     unsigned int screen,
+                     unsigned int flags)
+{
+    VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
+    IConsole *console = NULL;
+    vboxIID iid = VBOX_IID_INITIALIZER;
+    IMachine *machine = NULL;
+    nsresult rc;
+    char *tmp;
+    int tmp_fd = -1;
+    unsigned int max_screen;
+
+    virCheckFlags(0, NULL);
+
+    vboxIIDFromUUID(&iid, dom->uuid);
+    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_NO_DOMAIN, "%s",
+                       _("no domain with matching uuid"));
+        return NULL;
+    }
+
+    rc = machine->vtbl->GetMonitorCount(machine, &max_screen);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                       _("unable to get monitor count"));
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
 
-                            if (hddAttachment) {
-                                IHardDisk *hdd = NULL;
+    if (screen >= max_screen) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("screen ID higher than monitor "
+                         "count (%d)"), max_screen);
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
 
-#if VBOX_API_VERSION < 3001000
-                                rc = hddAttachment->vtbl->GetHardDisk(hddAttachment, &hdd);
-#else  /* VBOX_API_VERSION >= 3001000 */
-                                rc = hddAttachment->vtbl->GetMedium(hddAttachment, &hdd);
-#endif /* VBOX_API_VERSION >= 3001000 */
-                                if (NS_SUCCEEDED(rc) && hdd) {
-                                    vboxIID iid = VBOX_IID_INITIALIZER;
+    if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) {
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
 
-                                    rc = VBOX_MEDIUM_FUNC_ARG1(hdd, GetId, &iid.value);
-                                    if (NS_SUCCEEDED(rc)) {
+    if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
+        virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
+        VIR_FREE(tmp);
+        VBOX_RELEASE(machine);
+        return NULL;
+    }
 
-                                            DEBUGIID("HardDisk (to delete) UUID", hddIID.value);
-                                            DEBUGIID("HardDisk (currently processing) UUID", iid.value);
 
-                                        if (vboxIIDIsEqual(&hddIID, &iid)) {
-                                            PRUnichar *controller = NULL;
-                                            PRInt32    port       = 0;
-                                            PRInt32    device     = 0;
+    rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
+    if (NS_SUCCEEDED(rc)) {
+        rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
+        if (NS_SUCCEEDED(rc) && console) {
+            IDisplay *display = NULL;
 
-                                            DEBUGIID("Found HardDisk to delete, UUID", hddIID.value);
+            console->vtbl->GetDisplay(console, &display);
 
-                                            hddAttachment->vtbl->GetController(hddAttachment, &controller);
-                                            hddAttachment->vtbl->GetPort(hddAttachment, &port);
-                                            hddAttachment->vtbl->GetDevice(hddAttachment, &device);
+            if (display) {
+                PRUint32 width, height, bitsPerPixel;
+                PRUint32 screenDataSize;
+                PRUint8 *screenData;
+# if VBOX_API_VERSION >= 4003000
+                PRInt32 xOrigin, yOrigin;
+# endif
 
-#if VBOX_API_VERSION < 3001000
-                                            rc = machine->vtbl->DetachHardDisk(machine, controller, port, device);
-#else  /* VBOX_API_VERSION >= 3001000 */
-                                            rc = machine->vtbl->DetachDevice(machine, controller, port, device);
-#endif /* VBOX_API_VERSION >= 3001000 */
-                                            if (NS_SUCCEEDED(rc)) {
-                                                rc = machine->vtbl->SaveSettings(machine);
-                                                VIR_DEBUG("saving machine settings");
-                                            }
+                rc = display->vtbl->GetScreenResolution(display, screen,
+                                                        &width, &height,
+# if VBOX_API_VERSION < 4003000
+                                                        &bitsPerPixel);
+# else
+                                                        &bitsPerPixel,
+                                                        &xOrigin, &yOrigin);
+# endif
 
-                                            if (NS_SUCCEEDED(rc)) {
-                                                deregister++;
-                                                VIR_DEBUG("deregistering hdd:%d", deregister);
-                                            }
+                if (NS_FAILED(rc) || !width || !height) {
+                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                                   _("unable to get screen resolution"));
+                    goto endjob;
+                }
 
-                                            VBOX_UTF16_FREE(controller);
-                                        }
-                                        vboxIIDUnalloc(&iid);
-                                    }
-                                    VBOX_MEDIUM_RELEASE(hdd);
-                                }
-                            }
-                        }
-                        vboxArrayRelease(&hddAttachments);
-                        VBOX_RELEASE(machine);
-                    }
-                    VBOX_SESSION_CLOSE();
+                rc = display->vtbl->TakeScreenShotPNGToArray(display, screen,
+                                                             width, height,
+                                                             &screenDataSize,
+                                                             &screenData);
+                if (NS_FAILED(rc)) {
+                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                                   _("failed to take screenshot"));
+                    goto endjob;
                 }
 
-                vboxIIDUnalloc(&machineId);
-            }
+                if (safewrite(tmp_fd, (char *) screenData,
+                              screenDataSize) < 0) {
+                    virReportSystemError(errno, _("unable to write data "
+                                                  "to '%s'"), tmp);
+                    goto endjob;
+                }
 
-            vboxArrayUnalloc(&machineIds);
+                if (VIR_CLOSE(tmp_fd) < 0) {
+                    virReportSystemError(errno, _("unable to close %s"), tmp);
+                    goto endjob;
+                }
 
-            if (machineIdsSize == 0 || machineIdsSize == deregister) {
-                IProgress *progress = NULL;
-                rc = hardDisk->vtbl->DeleteStorage(hardDisk, &progress);
+                if (VIR_STRDUP(ret, "image/png") < 0)
+                    goto endjob;
 
-                if (NS_SUCCEEDED(rc) && progress) {
-                    progress->vtbl->WaitForCompletion(progress, -1);
-                    VBOX_RELEASE(progress);
-                    DEBUGIID("HardDisk deleted, UUID", hddIID.value);
-                    ret = 0;
+                if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
+                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                                   _("unable to open stream"));
+                    VIR_FREE(ret);
                 }
+ endjob:
+                VIR_FREE(screenData);
+                VBOX_RELEASE(display);
             }
+            VBOX_RELEASE(console);
         }
-
-        VBOX_MEDIUM_RELEASE(hardDisk);
+        VBOX_SESSION_CLOSE();
     }
 
-    vboxIIDUnalloc(&hddIID);
-
+    VIR_FORCE_CLOSE(tmp_fd);
+    unlink(tmp);
+    VIR_FREE(tmp);
+    VBOX_RELEASE(machine);
+    vboxIIDUnalloc(&iid);
     return ret;
 }
+#endif /* VBOX_API_VERSION >= 4000000 */
 
+
+#define MATCH(FLAG) (flags & (FLAG))
 static int
-vboxStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr info)
+vboxConnectListAllDomains(virConnectPtr conn,
+                          virDomainPtr **domains,
+                          unsigned int flags)
 {
-    VBOX_OBJECT_CHECK(vol->conn, int, -1);
-    IHardDisk *hardDisk  = NULL;
+    VBOX_OBJECT_CHECK(conn, int, -1);
+    vboxArray machines = VBOX_ARRAY_INITIALIZER;
+    char      *machineNameUtf8  = NULL;
+    PRUnichar *machineNameUtf16 = NULL;
     unsigned char uuid[VIR_UUID_BUFLEN];
-    vboxIID hddIID = VBOX_IID_INITIALIZER;
+    vboxIID iid = VBOX_IID_INITIALIZER;
+    PRUint32 state;
     nsresult rc;
+    size_t i;
+    virDomainPtr dom;
+    virDomainPtr *doms = NULL;
+    int count = 0;
+    bool active;
+    PRUint32 snapshotCount;
 
-    if (!info)
-        return ret;
+    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
 
-    if (virUUIDParse(vol->key, uuid) < 0) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("Could not parse UUID from '%s'"), vol->key);
-        return ret;
+    /* filter out flag options that will produce 0 results in vbox driver:
+     * - managed save: vbox guests don't have managed save images
+     * - autostart: vbox doesn't support autostarting guests
+     * - persistance: vbox doesn't support transient guests
+     */
+    if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
+         !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) ||
+        (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) &&
+         !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) ||
+        (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) &&
+         !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) {
+        if (domains &&
+            VIR_ALLOC_N(*domains, 1) < 0)
+            goto cleanup;
+
+        ret = 0;
+        goto cleanup;
     }
 
-    vboxIIDFromUUID(&hddIID, uuid);
-#if VBOX_API_VERSION < 4000000
-    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
-#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, &hardDisk);
-#else
-    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, AccessMode_ReadWrite,
-                                         PR_FALSE, &hardDisk);
-#endif /* VBOX_API_VERSION >= 4000000 */
-    if (NS_SUCCEEDED(rc)) {
-        PRUint32 hddstate;
+    rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not get list of domains, rc=%08x"), (unsigned)rc);
+        goto cleanup;
+    }
+
+    if (domains &&
+        VIR_ALLOC_N(doms, machines.count + 1) < 0)
+        goto cleanup;
+
+    for (i = 0; i < machines.count; i++) {
+        IMachine *machine = machines.items[i];
+
+        if (machine) {
+            PRBool isAccessible = PR_FALSE;
+            machine->vtbl->GetAccessible(machine, &isAccessible);
+            if (isAccessible) {
+                machine->vtbl->GetState(machine, &state);
+
+                if (state >= MachineState_FirstOnline &&
+                    state <= MachineState_LastOnline)
+                    active = true;
+                else
+                    active = false;
+
+                /* filter by active state */
+                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) &&
+                    !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) ||
+                      (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active)))
+                    continue;
+
+                /* filter by snapshot existence */
+                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) {
+                    rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount);
+                    if (NS_FAILED(rc)) {
+                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                       _("could not get snapshot count for listed domains"));
+                        goto cleanup;
+                    }
+                    if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) &&
+                           snapshotCount > 0) ||
+                          (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) &&
+                           snapshotCount == 0)))
+                        continue;
+                }
+
+                /* filter by machine state */
+                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) &&
+                    !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
+                       state == MachineState_Running) ||
+                      (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
+                       state == MachineState_Paused) ||
+                      (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
+                       state == MachineState_PoweredOff) ||
+                      (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
+                       (state != MachineState_Running &&
+                        state != MachineState_Paused &&
+                        state != MachineState_PoweredOff))))
+                    continue;
 
-        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
-        if (hddstate != MediaState_Inaccessible) {
-#if VBOX_API_VERSION < 4000000
-            PRUint64 hddLogicalSize;
-            PRUint64 hddActualSize;
-#else /* VBOX_API_VERSION >= 4000000 */
-            PRInt64 hddLogicalSize;
-            PRInt64 hddActualSize;
-#endif /* VBOX_API_VERSION >= 4000000 */
+                /* just count the machines */
+                if (!doms) {
+                    count++;
+                    continue;
+                }
 
-            info->type = VIR_STORAGE_VOL_FILE;
+                machine->vtbl->GetName(machine, &machineNameUtf16);
+                VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
+                machine->vtbl->GetId(machine, &iid.value);
+                vboxIIDToUUID(&iid, uuid);
+                vboxIIDUnalloc(&iid);
 
-            hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
-#if VBOX_API_VERSION < 4000000
-            info->capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
-#else /* VBOX_API_VERSION >= 4000000 */
-            info->capacity = hddLogicalSize;
-#endif /* VBOX_API_VERSION >= 4000000 */
+                dom = virGetDomain(conn, machineNameUtf8, uuid);
 
-            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
-            info->allocation = hddActualSize;
+                VBOX_UTF8_FREE(machineNameUtf8);
+                VBOX_UTF16_FREE(machineNameUtf16);
 
-            ret = 0;
+                if (!dom)
+                    goto cleanup;
 
-            VIR_DEBUG("Storage Volume Name: %s", vol->name);
-            VIR_DEBUG("Storage Volume Type: %s", info->type == VIR_STORAGE_VOL_BLOCK ? "Block" : "File");
-            VIR_DEBUG("Storage Volume Capacity: %llu", info->capacity);
-            VIR_DEBUG("Storage Volume Allocation: %llu", info->allocation);
+                if (active)
+                    dom->id = i + 1;
+
+                doms[count++] = dom;
+            }
         }
+    }
 
-        VBOX_MEDIUM_RELEASE(hardDisk);
+    if (doms) {
+        /* safe to ignore, new size will be equal or less than
+         * previous allocation*/
+        ignore_value(VIR_REALLOC_N(doms, count + 1));
+        *domains = doms;
+        doms = NULL;
     }
 
-    vboxIIDUnalloc(&hddIID);
+    ret = count;
+
+ cleanup:
+    if (doms) {
+        for (i = 0; i < count; i++) {
+            if (doms[i])
+                virDomainFree(doms[i]);
+        }
+    }
+    VIR_FREE(doms);
 
+    vboxArrayRelease(&machines);
     return ret;
 }
+#undef MATCH
 
-static char *vboxStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
-{
-    VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
-    IHardDisk *hardDisk  = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    vboxIID hddIID = VBOX_IID_INITIALIZER;
-    virStoragePoolDef pool;
-    virStorageVolDef def;
-    int defOk = 0;
-    nsresult rc;
-
-    virCheckFlags(0, NULL);
 
-    memset(&pool, 0, sizeof(pool));
-    memset(&def, 0, sizeof(def));
+static int
+vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
+                virNodeInfoPtr nodeinfo)
+{
+    return nodeGetInfo(nodeinfo);
+}
 
-    if (virUUIDParse(vol->key, uuid) < 0) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("Could not parse UUID from '%s'"), vol->key);
-        return ret;
-    }
 
-    vboxIIDFromUUID(&hddIID, uuid);
-#if VBOX_API_VERSION < 4000000
-    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
-#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, &hardDisk);
-#else
-    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, AccessMode_ReadWrite,
-                                         PR_FALSE, &hardDisk);
-#endif /* VBOX_API_VERSION >= 4000000 */
-    if (NS_SUCCEEDED(rc)) {
-        PRUint32 hddstate;
+static int
+vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           unsigned long long *freeMems,
+                           int startCell,
+                           int maxCells)
+{
+    return nodeGetCellsFreeMemory(freeMems, startCell, maxCells);
+}
 
-        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
-        if (NS_SUCCEEDED(rc) && hddstate != MediaState_Inaccessible) {
-            PRUnichar *hddFormatUtf16 = NULL;
-#if VBOX_API_VERSION < 4000000
-            PRUint64 hddLogicalSize;
-            PRUint64 hddActualSize;
-#else /* VBOX_API_VERSION >= 4000000 */
-            PRInt64 hddLogicalSize;
-            PRInt64 hddActualSize;
-#endif /* VBOX_API_VERSION >= 4000000 */
 
-            /* since there is currently one default pool now
-             * and virStorageVolDefFormat() just checks it type
-             * so just assign it for now, change the behaviour
-             * when vbox supports pools.
-             */
-            pool.type = VIR_STORAGE_POOL_DIR;
-            def.type = VIR_STORAGE_VOL_FILE;
-            defOk = 1;
+static unsigned long long
+vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    unsigned long long freeMem;
+    if (nodeGetMemory(NULL, &freeMem) < 0)
+        return 0;
+    return freeMem;
+}
 
-            rc = hardDisk->vtbl->GetLogicalSize(hardDisk, &hddLogicalSize);
-            if (NS_SUCCEEDED(rc) && defOk) {
-#if VBOX_API_VERSION < 4000000
-                def.target.capacity = hddLogicalSize * 1024 * 1024; /* MB => Bytes */
-#else /* VBOX_API_VERSION >= 4000000 */
-                def.target.capacity = hddLogicalSize;
-#endif /* VBOX_API_VERSION >= 4000000 */
-            } else
-                defOk = 0;
 
-            rc = VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetSize, &hddActualSize);
-            if (NS_SUCCEEDED(rc) && defOk)
-                def.target.allocation = hddActualSize;
-            else
-                defOk = 0;
+static int
+vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED,
+                     unsigned int npages,
+                     unsigned int *pages,
+                     int startCell,
+                     unsigned int cellCount,
+                     unsigned long long *counts,
+                     unsigned int flags)
+{
+    virCheckFlags(0, -1);
 
-            if (VIR_STRDUP(def.name, vol->name) < 0)
-                defOk = 0;
+    return nodeGetFreePages(npages, pages, startCell, cellCount, counts);
+}
 
-            if (VIR_STRDUP(def.key, vol->key) < 0)
-                defOk = 0;
+static int _pfnInitialize(vboxGlobalData *data)
+{
+    data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
+    if (data->pFuncs == NULL)
+        return -1;
+#if VBOX_XPCOMC_VERSION == 0x00010000U
+    data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession);
+#else  /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
+    data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession);
+#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
+    return 0;
+}
 
-            rc = hardDisk->vtbl->GetFormat(hardDisk, &hddFormatUtf16);
-            if (NS_SUCCEEDED(rc) && defOk) {
-                char *hddFormatUtf8 = NULL;
+static int
+_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
+    /* No event queue functionality in 2.2.* and 4.* as of now */
+    vboxUnsupported();
+#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
+    /* Initialize the fWatch needed for Event Callbacks */
+    data->fdWatch = -1;
+    data->pFuncs->pfnGetEventQueue(&data->vboxQueue);
+    if (data->vboxQueue == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("nsIEventQueue object is null"));
+        return -1;
+    }
+#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
+    return 0;
+}
 
-                VBOX_UTF16_TO_UTF8(hddFormatUtf16, &hddFormatUtf8);
-                if (hddFormatUtf8) {
+static
+void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION == 2002000
+    vboxUnsupported();
+#else /* VBOX_API_VERSION != 2002000 */
+    g_pVBoxGlobalData = data;
+#endif /* VBOX_API_VERSION != 2002000 */
+}
 
-                    VIR_DEBUG("Storage Volume Format: %s", hddFormatUtf8);
+#if VBOX_API_VERSION < 4000000
 
-                    if (STRCASEEQ("vmdk", hddFormatUtf8))
-                        def.target.format = VIR_STORAGE_FILE_VMDK;
-                    else if (STRCASEEQ("vhd", hddFormatUtf8))
-                        def.target.format = VIR_STORAGE_FILE_VPC;
-                    else if (STRCASEEQ("vdi", hddFormatUtf8))
-                        def.target.format = VIR_STORAGE_FILE_VDI;
-                    else
-                        def.target.format = VIR_STORAGE_FILE_RAW;
+# if VBOX_API_VERSION < 3001000
+static void
+_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED,
+               IMachine *machine, PRUnichar *hddcnameUtf16)
+{
+    /* Disconnect all the drives if present */
+    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0);
+    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1);
+    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1);
+}
+# else  /* VBOX_API_VERSION >= 3001000 */
+static void
+_detachDevices(vboxGlobalData *data, IMachine *machine,
+               PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED)
+{
+    /* get all the controller first, then the attachments and
+    * remove them all so that the machine can be undefined
+    */
+   vboxArray storageControllers = VBOX_ARRAY_INITIALIZER;
+   size_t i = 0, j = 0;
 
-                    VBOX_UTF8_FREE(hddFormatUtf8);
-                }
+   vboxArrayGet(&storageControllers, machine,
+                machine->vtbl->GetStorageControllers);
 
-                VBOX_UTF16_FREE(hddFormatUtf16);
-            } else {
-                defOk = 0;
-            }
-        }
+   for (i = 0; i < storageControllers.count; i++) {
+       IStorageController *strCtl = storageControllers.items[i];
+       PRUnichar *strCtlName = NULL;
+       vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
 
-        VBOX_MEDIUM_RELEASE(hardDisk);
-    }
+       if (!strCtl)
+           continue;
 
-    vboxIIDUnalloc(&hddIID);
+       strCtl->vtbl->GetName(strCtl, &strCtlName);
+       vboxArrayGetWithPtrArg(&mediumAttachments, machine,
+                              machine->vtbl->GetMediumAttachmentsOfController,
+                              strCtlName);
 
-    if (defOk)
-        ret = virStorageVolDefFormat(&pool, &def);
+       for (j = 0; j < mediumAttachments.count; j++) {
+           IMediumAttachment *medAtt = mediumAttachments.items[j];
+           PRInt32 port = ~0U;
+           PRInt32 device = ~0U;
 
-    return ret;
-}
+           if (!medAtt)
+               continue;
 
-static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
-    VBOX_OBJECT_CHECK(vol->conn, char *, NULL);
-    IHardDisk *hardDisk  = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
-    vboxIID hddIID = VBOX_IID_INITIALIZER;
-    nsresult rc;
+           medAtt->vtbl->GetPort(medAtt, &port);
+           medAtt->vtbl->GetDevice(medAtt, &device);
 
-    if (virUUIDParse(vol->key, uuid) < 0) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("Could not parse UUID from '%s'"), vol->key);
-        return ret;
-    }
+           if ((port != ~0U) && (device != ~0U)) {
+               machine->vtbl->DetachDevice(machine,
+                                           strCtlName,
+                                           port,
+                                           device);
+           }
+       }
+       vboxArrayRelease(&storageControllers);
+       machine->vtbl->RemoveStorageController(machine, strCtlName);
+       VBOX_UTF16_FREE(strCtlName);
+   }
+   vboxArrayRelease(&storageControllers);
+}
+# endif /* VBOX_API_VERSION >= 3001000 */
 
-    vboxIIDFromUUID(&hddIID, uuid);
-#if VBOX_API_VERSION < 4000000
-    rc = data->vboxObj->vtbl->GetHardDisk(data->vboxObj, hddIID.value, &hardDisk);
-#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
-    rc = data->vboxObj->vtbl->FindMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, &hardDisk);
-#else
-    rc = data->vboxObj->vtbl->OpenMedium(data->vboxObj, hddIID.value,
-                                         DeviceType_HardDisk, AccessMode_ReadWrite,
-                                         PR_FALSE, &hardDisk);
-#endif /* VBOX_API_VERSION >= 4000000 */
-    if (NS_SUCCEEDED(rc)) {
-        PRUint32 hddstate;
+static nsresult
+_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine)
+{
+    return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine);
+}
 
-        VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetState, &hddstate);
-        if (hddstate != MediaState_Inaccessible) {
-            PRUnichar *hddLocationUtf16 = NULL;
-            char      *hddLocationUtf8  = NULL;
+static void
+_deleteConfig(IMachine *machine)
+{
+    machine->vtbl->DeleteSettings(machine);
+}
 
-            VBOX_MEDIUM_FUNC_ARG1(hardDisk, GetLocation, &hddLocationUtf16);
+#else /* VBOX_API_VERSION >= 4000000 */
 
-            VBOX_UTF16_TO_UTF8(hddLocationUtf16, &hddLocationUtf8);
-            if (hddLocationUtf8) {
+static void
+_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED,
+               IMachine *machine ATTRIBUTE_UNUSED,
+               PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED)
+{
+    vboxUnsupported();
+}
 
-                ignore_value(VIR_STRDUP(ret, hddLocationUtf8));
+static nsresult
+_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine)
+{
+    nsresult rc;
+    vboxArray media = VBOX_ARRAY_INITIALIZER;
+    rc = VBOX_OBJECT_GET_MACHINE(IID_MEMBER(value), machine);
+    if (NS_FAILED(rc)) {
+        virReportError(VIR_ERR_NO_DOMAIN, "%s",
+                       _("no domain with matching uuid"));
+        return rc;
+    }
 
-                VIR_DEBUG("Storage Volume Name: %s", vol->name);
-                VIR_DEBUG("Storage Volume Path: %s", hddLocationUtf8);
-                VIR_DEBUG("Storage Volume Pool: %s", vol->pool);
+    /* We're not interested in the array returned by the Unregister method,
+     * but in the side effect of unregistering the virtual machine. In order
+     * to call the Unregister method correctly we need to use the vboxArray
+     * wrapper here. */
+    rc = vboxArrayGetWithUintArg(&media, *machine, (*machine)->vtbl->Unregister,
+                                 CleanupMode_DetachAllReturnNone);
+    vboxArrayUnalloc(&media);
+    return rc;
+}
 
-                VBOX_UTF8_FREE(hddLocationUtf8);
-            }
+static void
+_deleteConfig(IMachine *machine)
+{
+    IProgress *progress = NULL;
 
-            VBOX_UTF16_FREE(hddLocationUtf16);
-        }
+    /* The IMachine Delete method takes an array of IMedium items to be
+     * deleted along with the virtual machine. We just want to pass an
+     * empty array. But instead of adding a full vboxArraySetWithReturn to
+     * the glue layer (in order to handle the required signature of the
+     * Delete method) we use a local solution here. */
+# ifdef WIN32
+    SAFEARRAY *safeArray = NULL;
+    typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self,
+                                                 SAFEARRAY **media,
+                                                 IProgress **progress);
 
-        VBOX_MEDIUM_RELEASE(hardDisk);
+#  if VBOX_API_VERSION < 4003000
+    ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress);
+#  else
+    ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress);
+#  endif
+# else
+    /* XPCOM doesn't like NULL as an array, even when the array size is 0.
+     * Instead pass it a dummy array to avoid passing NULL. */
+    IMedium *array[] = { NULL };
+#  if VBOX_API_VERSION < 4003000
+    machine->vtbl->Delete(machine, 0, array, &progress);
+#  else
+    machine->vtbl->DeleteConfig(machine, 0, array, &progress);
+#  endif
+# endif
+    if (progress != NULL) {
+        progress->vtbl->WaitForCompletion(progress, -1);
+        VBOX_RELEASE(progress);
     }
+}
 
-    vboxIIDUnalloc(&hddIID);
+#endif /* VBOX_API_VERSION >= 4000000 */
 
-    return ret;
+static void _pfnUninitialize(vboxGlobalData *data)
+{
+    if (data->pFuncs)
+        data->pFuncs->pfnComUninitialize();
 }
 
-#if VBOX_API_VERSION >= 4000000
-static char *
-vboxDomainScreenshot(virDomainPtr dom,
-                     virStreamPtr st,
-                     unsigned int screen,
-                     unsigned int flags)
+static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv)
 {
-    VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
-    IConsole *console = NULL;
-    vboxIID iid = VBOX_IID_INITIALIZER;
-    IMachine *machine = NULL;
-    nsresult rc;
-    char *tmp;
-    int tmp_fd = -1;
-    unsigned int max_screen;
+    pFuncs->pfnComUnallocMem(pv);
+}
 
-    virCheckFlags(0, NULL);
+static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString)
+{
+    pFuncs->pfnUtf16Free(pwszString);
+}
 
-    vboxIIDFromUUID(&iid, dom->uuid);
-    rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_NO_DOMAIN, "%s",
-                       _("no domain with matching uuid"));
-        return NULL;
-    }
+static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString)
+{
+    pFuncs->pfnUtf8Free(pszString);
+}
 
-    rc = machine->vtbl->GetMonitorCount(machine, &max_screen);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                       _("unable to get monitor count"));
-        VBOX_RELEASE(machine);
-        return NULL;
-    }
+static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString)
+{
+    return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString);
+}
 
-    if (screen >= max_screen) {
-        virReportError(VIR_ERR_INVALID_ARG,
-                       _("screen ID higher than monitor "
-                         "count (%d)"), max_screen);
-        VBOX_RELEASE(machine);
-        return NULL;
-    }
+static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString)
+{
+    return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString);
+}
 
-    if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX", LOCALSTATEDIR) < 0) {
-        VBOX_RELEASE(machine);
-        return NULL;
-    }
+#if VBOX_API_VERSION == 2002000
 
-    if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
-        virReportSystemError(errno, _("mkostemp(\"%s\") failed"), tmp);
-        VIR_FREE(tmp);
-        VBOX_RELEASE(machine);
-        return NULL;
-    }
+static void _vboxIIDInitialize(vboxIIDUnion *iidu)
+{
+    memset(iidu, 0, sizeof(vboxIIDUnion));
+}
 
+static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu)
+{
+# ifdef WIN32
+    DEBUGUUID(msg, (nsID *)&IID_MEMBER(value));
+# else /* !WIN32 */
+    DEBUGUUID(msg, IID_MEMBER(value));
+# endif /* !WIN32 */
+}
 
-    rc = VBOX_SESSION_OPEN_EXISTING(iid.value, machine);
-    if (NS_SUCCEEDED(rc)) {
-        rc = data->vboxSession->vtbl->GetConsole(data->vboxSession, &console);
-        if (NS_SUCCEEDED(rc) && console) {
-            IDisplay *display = NULL;
+#else /* VBOX_API_VERSION != 2002000 */
 
-            console->vtbl->GetDisplay(console, &display);
+static void _vboxIIDInitialize(vboxIIDUnion *iidu)
+{
+    memset(iidu, 0, sizeof(vboxIIDUnion));
+    IID_MEMBER(owner) = true;
+}
 
-            if (display) {
-                PRUint32 width, height, bitsPerPixel;
-                PRUint32 screenDataSize;
-                PRUint8 *screenData;
-# if VBOX_API_VERSION >= 4003000
-                PRInt32 xOrigin, yOrigin;
-# endif
+static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu)
+{
+    DEBUGPRUnichar(msg, IID_MEMBER(value));
+}
 
-                rc = display->vtbl->GetScreenResolution(display, screen,
-                                                        &width, &height,
-# if VBOX_API_VERSION < 4003000
-                                                        &bitsPerPixel);
-# else
-                                                        &bitsPerPixel,
-                                                        &xOrigin, &yOrigin);
-# endif
+#endif /* VBOX_API_VERSION != 2002000 */
 
-                if (NS_FAILED(rc) || !width || !height) {
-                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                                   _("unable to get screen resolution"));
-                    goto endjob;
-                }
+static void* _handleGetMachines(IVirtualBox *vboxObj)
+{
+    return vboxObj->vtbl->GetMachines;
+}
 
-                rc = display->vtbl->TakeScreenShotPNGToArray(display, screen,
-                                                             width, height,
-                                                             &screenDataSize,
-                                                             &screenData);
-                if (NS_FAILED(rc)) {
-                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                                   _("failed to take screenshot"));
-                    goto endjob;
-                }
+static nsresult _nsisupportsRelease(nsISupports *nsi)
+{
+    return nsi->vtbl->Release(nsi);
+}
 
-                if (safewrite(tmp_fd, (char *) screenData,
-                              screenDataSize) < 0) {
-                    virReportSystemError(errno, _("unable to write data "
-                                                  "to '%s'"), tmp);
-                    goto endjob;
-                }
+static nsresult
+_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16)
+{
+    return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16);
+}
 
-                if (VIR_CLOSE(tmp_fd) < 0) {
-                    virReportSystemError(errno, _("unable to close %s"), tmp);
-                    goto endjob;
-                }
+#if VBOX_API_VERSION < 4000000
 
-                if (VIR_STRDUP(ret, "image/png") < 0)
-                    goto endjob;
+static nsresult
+_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine)
+{
+    return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine);
+}
 
-                if (virFDStreamOpenFile(st, tmp, 0, 0, O_RDONLY) < 0) {
-                    virReportError(VIR_ERR_OPERATION_FAILED, "%s",
-                                   _("unable to open stream"));
-                    VIR_FREE(ret);
-                }
- endjob:
-                VIR_FREE(screenData);
-                VBOX_RELEASE(display);
-            }
-            VBOX_RELEASE(console);
-        }
-        VBOX_SESSION_CLOSE();
-    }
+#else /* VBOX_API_VERSION >= 4000000 */
 
-    VIR_FORCE_CLOSE(tmp_fd);
-    unlink(tmp);
-    VIR_FREE(tmp);
-    VBOX_RELEASE(machine);
-    vboxIIDUnalloc(&iid);
-    return ret;
+static nsresult
+_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine)
+{
+    return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine);
 }
+
 #endif /* VBOX_API_VERSION >= 4000000 */
 
+static nsresult
+_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties)
+{
+    return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties);
+}
 
-#define MATCH(FLAG) (flags & (FLAG))
-static int
-vboxConnectListAllDomains(virConnectPtr conn,
-                          virDomainPtr **domains,
-                          unsigned int flags)
+static nsresult
+_virtualboxCreateMachine(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr ATTRIBUTE_UNUSED)
 {
-    VBOX_OBJECT_CHECK(conn, int, -1);
-    vboxArray machines = VBOX_ARRAY_INITIALIZER;
-    char      *machineNameUtf8  = NULL;
-    PRUnichar *machineNameUtf16 = NULL;
-    unsigned char uuid[VIR_UUID_BUFLEN];
     vboxIID iid = VBOX_IID_INITIALIZER;
-    PRUint32 state;
+    PRUnichar *machineNameUtf16 = NULL;
     nsresult rc;
-    size_t i;
-    virDomainPtr dom;
-    virDomainPtr *doms = NULL;
-    int count = 0;
-    bool active;
-    PRUint32 snapshotCount;
-
-    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
-
-    /* filter out flag options that will produce 0 results in vbox driver:
-     * - managed save: vbox guests don't have managed save images
-     * - autostart: vbox doesn't support autostarting guests
-     * - persistance: vbox doesn't support transient guests
-     */
-    if ((MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
-         !MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT)) ||
-        (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) &&
-         !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART)) ||
-        (MATCH(VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE) &&
-         !MATCH(VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE))) {
-        if (domains &&
-            VIR_ALLOC_N(*domains, 1) < 0)
-            goto cleanup;
-
-        ret = 0;
-        goto cleanup;
-    }
 
-    rc = vboxArrayGet(&machines, data->vboxObj, data->vboxObj->vtbl->GetMachines);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Could not get list of domains, rc=%08x"), (unsigned)rc);
-        goto cleanup;
+    VBOX_UTF8_TO_UTF16(def->name, &machineNameUtf16);
+    vboxIIDFromUUID(&iid, def->uuid);
+    {
+#if VBOX_API_VERSION < 3002000
+        rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
+                                                    machineNameUtf16,
+                                                    NULL,
+                                                    NULL,
+                                                    iid.value,
+                                                    machine);
+#elif VBOX_API_VERSION < 4000000 /* 3002000 <= VBOX_API_VERSION < 4000000 */
+        PRBool override             = PR_FALSE;
+        rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
+                                                machineNameUtf16,
+                                                NULL,
+                                                NULL,
+                                                iid.value,
+                                                override,
+                                                machine);
+#elif VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
+        PRBool override             = PR_FALSE;
+        rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
+                                                NULL,
+                                                machineNameUtf16,
+                                                NULL,
+                                                iid.value,
+                                                override,
+                                                machine);
+#else /* VBOX_API_VERSION >= 4002000 */
+        const char *flagsUUIDPrefix = "UUID=";
+        const char *flagsForceOverwrite = "forceOverwrite=0";
+        const char *flagsSeparator = ",";
+        char createFlags[strlen(flagsUUIDPrefix) + VIR_UUID_STRING_BUFLEN + strlen(flagsSeparator) + strlen(flagsForceOverwrite) + 1];
+        PRUnichar *createFlagsUtf16 = NULL;
+
+        snprintf(createFlags, sizeof(createFlags), "%s%s%s%s",
+                 flagsUUIDPrefix,
+                 uuidstr,
+                 flagsSeparator,
+                 flagsForceOverwrite
+                );
+        VBOX_UTF8_TO_UTF16(createFlags, &createFlagsUtf16);
+        rc = data->vboxObj->vtbl->CreateMachine(data->vboxObj,
+                                                NULL,
+                                                machineNameUtf16,
+                                                0,
+                                                nsnull,
+                                                nsnull,
+                                                createFlagsUtf16,
+                                                machine);
+#endif /* VBOX_API_VERSION >= 4002000 */
     }
+    VBOX_UTF16_FREE(machineNameUtf16);
+    vboxIIDUnalloc(&iid);
+    return rc;
+}
 
-    if (domains &&
-        VIR_ALLOC_N(doms, machines.count + 1) < 0)
-        goto cleanup;
-
-    for (i = 0; i < machines.count; i++) {
-        IMachine *machine = machines.items[i];
-
-        if (machine) {
-            PRBool isAccessible = PR_FALSE;
-            machine->vtbl->GetAccessible(machine, &isAccessible);
-            if (isAccessible) {
-                machine->vtbl->GetState(machine, &state);
+static nsresult
+_virtualboxRegisterMachine(IVirtualBox *vboxObj, IMachine *machine)
+{
+    return vboxObj->vtbl->RegisterMachine(vboxObj, machine);
+}
 
-                if (state >= MachineState_FirstOnline &&
-                    state <= MachineState_LastOnline)
-                    active = true;
-                else
-                    active = false;
+static nsresult
+_virtualboxFindMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED,
+                      PRUnichar *location ATTRIBUTE_UNUSED,
+                      PRUint32 deviceType ATTRIBUTE_UNUSED,
+                      PRUint32 accessMode ATTRIBUTE_UNUSED,
+                      IMedium **medium ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION >= 4000000 && VBOX_API_VERSION < 4002000
+    return vboxObj->vtbl->FindMedium(vboxObj, location,
+                                     deviceType, medium);
+#elif VBOX_API_VERSION >= 4002000
+    return vboxObj->vtbl->OpenMedium(vboxObj, location,
+                                     deviceType, accessMode, PR_FALSE, medium);
+#else
+    vboxUnsupported();
+    return 0;
+#endif
+}
 
-                /* filter by active state */
-                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE) &&
-                    !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) && active) ||
-                      (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) && !active)))
-                    continue;
+static nsresult
+_virtualboxOpenMedium(IVirtualBox *vboxObj ATTRIBUTE_UNUSED,
+                      PRUnichar *location ATTRIBUTE_UNUSED,
+                      PRUint32 deviceType ATTRIBUTE_UNUSED,
+                      PRUint32 accessMode ATTRIBUTE_UNUSED,
+                      IMedium **medium ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION == 4000000
+    return vboxObj->vtbl->OpenMedium(vboxObj,
+                                     location,
+                                     deviceType, accessMode,
+                                     medium);
+#elif VBOX_API_VERSION >= 4001000
+    return vboxObj->vtbl->OpenMedium(vboxObj,
+                                     location,
+                                     deviceType, accessMode,
+                                     false,
+                                     medium);
+#else
+    vboxUnsupported();
+    return 0;
+#endif
+}
 
-                /* filter by snapshot existence */
-                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_SNAPSHOT)) {
-                    rc = machine->vtbl->GetSnapshotCount(machine, &snapshotCount);
-                    if (NS_FAILED(rc)) {
-                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                                       _("could not get snapshot count for listed domains"));
-                        goto cleanup;
-                    }
-                    if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) &&
-                           snapshotCount > 0) ||
-                          (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) &&
-                           snapshotCount == 0)))
-                        continue;
-                }
+static nsresult
+_machineAddStorageController(IMachine *machine, PRUnichar *name,
+                             PRUint32 connectionType,
+                             IStorageController **controller)
+{
+    return machine->vtbl->AddStorageController(machine, name, connectionType,
+                                               controller);
+}
 
-                /* filter by machine state */
-                if (MATCH(VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE) &&
-                    !((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
-                       state == MachineState_Running) ||
-                      (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
-                       state == MachineState_Paused) ||
-                      (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
-                       state == MachineState_PoweredOff) ||
-                      (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
-                       (state != MachineState_Running &&
-                        state != MachineState_Paused &&
-                        state != MachineState_PoweredOff))))
-                    continue;
+static nsresult
+_machineAttachDevice(IMachine *machine ATTRIBUTE_UNUSED,
+                     PRUnichar *name ATTRIBUTE_UNUSED,
+                     PRInt32 controllerPort ATTRIBUTE_UNUSED,
+                     PRInt32 device ATTRIBUTE_UNUSED,
+                     PRUint32 type ATTRIBUTE_UNUSED,
+                     IMedium * medium ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION >= 4000000
+    return machine->vtbl->AttachDevice(machine, name, controllerPort,
+                                       device, type, medium);
+#else /* VBOX_API_VERSION < 4000000 */
+    vboxUnsupported();
+    return 0;
+#endif /* VBOX_API_VERSION < 4000000 */
+}
 
-                /* just count the machines */
-                if (!doms) {
-                    count++;
-                    continue;
-                }
+static nsresult
+_machineCreateSharedFolder(IMachine *machine, PRUnichar *name,
+                           PRUnichar *hostPath, PRBool writable,
+                           PRBool automount ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION < 4000000
+    return machine->vtbl->CreateSharedFolder(machine, name, hostPath,
+                                             writable);
+#else /* VBOX_API_VERSION >= 4000000 */
+    return machine->vtbl->CreateSharedFolder(machine, name, hostPath,
+                                             writable, automount);
+#endif /* VBOX_API_VERSION >= 4000000 */
+}
 
-                machine->vtbl->GetName(machine, &machineNameUtf16);
-                VBOX_UTF16_TO_UTF8(machineNameUtf16, &machineNameUtf8);
-                machine->vtbl->GetId(machine, &iid.value);
-                vboxIIDToUUID(&iid, uuid);
-                vboxIIDUnalloc(&iid);
 
-                dom = virGetDomain(conn, machineNameUtf8, uuid);
+static nsresult
+_machineGetAccessible(IMachine *machine, PRBool *isAccessible)
+{
+    return machine->vtbl->GetAccessible(machine, isAccessible);
+}
 
-                VBOX_UTF8_FREE(machineNameUtf8);
-                VBOX_UTF16_FREE(machineNameUtf16);
+static nsresult
+_machineGetState(IMachine *machine, PRUint32 *state)
+{
+    return machine->vtbl->GetState(machine, state);
+}
 
-                if (!dom)
-                    goto cleanup;
+static nsresult
+_machineGetName(IMachine *machine, PRUnichar **name)
+{
+    return machine->vtbl->GetName(machine, name);
+}
 
-                if (active)
-                    dom->id = i + 1;
+static nsresult
+_machineGetId(IMachine *machine, vboxIIDUnion *iidu)
+{
+    return machine->vtbl->GetId(machine, &IID_MEMBER(value));
+}
 
-                doms[count++] = dom;
-            }
-        }
-    }
+static nsresult
+_machineGetBIOSSettings(IMachine *machine, IBIOSSettings **bios)
+{
+    return machine->vtbl->GetBIOSSettings(machine, bios);
+}
 
-    if (doms) {
-        /* safe to ignore, new size will be equal or less than
-         * previous allocation*/
-        ignore_value(VIR_REALLOC_N(doms, count + 1));
-        *domains = doms;
-        doms = NULL;
-    }
+static nsresult
+_machineGetAudioAdapter(IMachine *machine, IAudioAdapter **audioadapter)
+{
+    return machine->vtbl->GetAudioAdapter(machine, audioadapter);
+}
 
-    ret = count;
+static nsresult
+_machineGetNetworkAdapter(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter)
+{
+    return machine->vtbl->GetNetworkAdapter(machine, slot, adapter);
+}
 
- cleanup:
-    if (doms) {
-        for (i = 0; i < count; i++) {
-            if (doms[i])
-                virDomainFree(doms[i]);
-        }
-    }
-    VIR_FREE(doms);
+static nsresult
+_machineGetChipsetType(IMachine *machine ATTRIBUTE_UNUSED, PRUint32 *chipsetType ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION >= 4001000
+    return machine->vtbl->GetChipsetType(machine, chipsetType);
+#else /* VBOX_API_VERSION < 4001000 */
+    vboxUnsupported();
+    return 0;
+#endif /* VBOX_API_VERSION < 4001000 */
+}
 
-    vboxArrayRelease(&machines);
-    return ret;
+static nsresult
+_machineGetSerialPort(IMachine *machine, PRUint32 slot, ISerialPort **port)
+{
+    return machine->vtbl->GetSerialPort(machine, slot, port);
 }
-#undef MATCH
 
+static nsresult
+_machineGetParallelPort(IMachine *machine, PRUint32 slot, IParallelPort **port)
+{
+    return machine->vtbl->GetParallelPort(machine, slot, port);
+}
 
-static int
-vboxNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
-                virNodeInfoPtr nodeinfo)
+static nsresult
+_machineGetVRDxServer(IMachine *machine, IVRDxServer **VRDxServer)
 {
-    return nodeGetInfo(nodeinfo);
+#if VBOX_API_VERSION < 4000000
+    return machine->vtbl->GetVRDPServer(machine, VRDxServer);
+#else /* VBOX_API_VERSION >= 4000000 */
+    return machine->vtbl->GetVRDEServer(machine, VRDxServer);
+#endif /* VBOX_API_VERSION >= 4000000 */
 }
 
+static nsresult
+_machineGetUSBCommon(IMachine *machine, IUSBCommon **USBCommon)
+{
+#if VBOX_API_VERSION < 4003000
+    return machine->vtbl->GetUSBController(machine, USBCommon);
+#else
+    return machine->vtbl->GetUSBDeviceFilters(machine, USBCommon);
+#endif
+}
 
-static int
-vboxNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED,
-                           unsigned long long *freeMems,
-                           int startCell,
-                           int maxCells)
+static nsresult
+_machineSetCPUCount(IMachine *machine, PRUint32 CPUCount)
 {
-    return nodeGetCellsFreeMemory(freeMems, startCell, maxCells);
+    return machine->vtbl->SetCPUCount(machine, CPUCount);
 }
 
+static nsresult
+_machineSetMemorySize(IMachine *machine, PRUint32 memorySize)
+{
+    return machine->vtbl->SetMemorySize(machine, memorySize);
+}
 
-static unsigned long long
-vboxNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED)
+static nsresult
+_machineSetCPUProperty(IMachine *machine, PRUint32 property ATTRIBUTE_UNUSED, PRBool value)
 {
-    unsigned long long freeMem;
-    if (nodeGetMemory(NULL, &freeMem) < 0)
-        return 0;
-    return freeMem;
+#if VBOX_API_VERSION < 3001000
+    return machine->vtbl->SetPAEEnabled(machine, value);
+#elif VBOX_API_VERSION == 3001000
+    return machine->vtbl->SetCpuProperty(machine, property, value);
+#elif VBOX_API_VERSION >= 3002000
+    return machine->vtbl->SetCPUProperty(machine, property, value);
+#endif
 }
 
+static nsresult
+_machineSetBootOrder(IMachine *machine, PRUint32 position, PRUint32 device)
+{
+    return machine->vtbl->SetBootOrder(machine, position, device);
+}
 
-static int
-vboxNodeGetFreePages(virConnectPtr conn ATTRIBUTE_UNUSED,
-                     unsigned int npages,
-                     unsigned int *pages,
-                     int startCell,
-                     unsigned int cellCount,
-                     unsigned long long *counts,
-                     unsigned int flags)
+static nsresult
+_machineSetVRAMSize(IMachine *machine, PRUint32 VRAMSize)
 {
-    virCheckFlags(0, -1);
+    return machine->vtbl->SetVRAMSize(machine, VRAMSize);
+}
 
-    return nodeGetFreePages(npages, pages, startCell, cellCount, counts);
+static nsresult
+_machineSetMonitorCount(IMachine *machine, PRUint32 monitorCount)
+{
+    return machine->vtbl->SetMonitorCount(machine, monitorCount);
 }
 
-static int _pfnInitialize(vboxGlobalData *data)
+static nsresult
+_machineSetAccelerate3DEnabled(IMachine *machine, PRBool accelerate3DEnabled)
 {
-    data->pFuncs = g_pfnGetFunctions(VBOX_XPCOMC_VERSION);
-    if (data->pFuncs == NULL)
-        return -1;
-#if VBOX_XPCOMC_VERSION == 0x00010000U
-    data->pFuncs->pfnComInitialize(&data->vboxObj, &data->vboxSession);
-#else  /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
-    data->pFuncs->pfnComInitialize(IVIRTUALBOX_IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession);
-#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */
-    return 0;
+    return machine->vtbl->SetAccelerate3DEnabled(machine, accelerate3DEnabled);
 }
 
-static int
-_initializeDomainEvent(vboxGlobalData *data ATTRIBUTE_UNUSED)
+static nsresult
+_machineSetAccelerate2DVideoEnabled(IMachine *machine ATTRIBUTE_UNUSED,
+                                    PRBool accelerate2DVideoEnabled ATTRIBUTE_UNUSED)
 {
-#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
-    /* No event queue functionality in 2.2.* and 4.* as of now */
+#if VBOX_API_VERSION >= 3001000
+    return machine->vtbl->SetAccelerate2DVideoEnabled(machine, accelerate2DVideoEnabled);
+#else /* VBOX_API_VERSION < 3001000 */
     vboxUnsupported();
-#else /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
-    /* Initialize the fWatch needed for Event Callbacks */
-    data->fdWatch = -1;
-    data->pFuncs->pfnGetEventQueue(&data->vboxQueue);
-    if (data->vboxQueue == NULL) {
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                       _("nsIEventQueue object is null"));
-        return -1;
-    }
-#endif /* VBOX_API_VERSION > 2002000 || VBOX_API_VERSION < 4000000 */
     return 0;
+#endif /* VBOX_API_VERSION < 3001000 */
 }
 
-static
-void _registerGlobalData(vboxGlobalData *data ATTRIBUTE_UNUSED)
+static nsresult
+_machineSetExtraData(IMachine *machine, PRUnichar *key, PRUnichar *value)
 {
-#if VBOX_API_VERSION == 2002000
-    vboxUnsupported();
-#else /* VBOX_API_VERSION != 2002000 */
-    g_pVBoxGlobalData = data;
-#endif /* VBOX_API_VERSION != 2002000 */
+    return machine->vtbl->SetExtraData(machine, key, value);
+}
+
+static nsresult
+_machineSaveSettings(IMachine *machine)
+{
+    return machine->vtbl->SaveSettings(machine);
 }
 
 #if VBOX_API_VERSION < 4000000
 
-# if VBOX_API_VERSION < 3001000
-static void
-_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED,
-               IMachine *machine, PRUnichar *hddcnameUtf16)
+static nsresult
+_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED)
 {
-    /* Disconnect all the drives if present */
-    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 0);
-    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 0, 1);
-    machine->vtbl->DetachHardDisk(machine, hddcnameUtf16, 1, 1);
+    return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value));
 }
-# else  /* VBOX_API_VERSION >= 3001000 */
-static void
-_detachDevices(vboxGlobalData *data, IMachine *machine,
-               PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED)
+
+static nsresult
+_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED)
 {
-    /* get all the controller first, then the attachments and
-    * remove them all so that the machine can be undefined
-    */
-   vboxArray storageControllers = VBOX_ARRAY_INITIALIZER;
-   size_t i = 0, j = 0;
+    return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value));
+}
 
-   vboxArrayGet(&storageControllers, machine,
-                machine->vtbl->GetStorageControllers);
+static nsresult
+_sessionClose(ISession *session)
+{
+    return session->vtbl->Close(session);
+}
 
-   for (i = 0; i < storageControllers.count; i++) {
-       IStorageController *strCtl = storageControllers.items[i];
-       PRUnichar *strCtlName = NULL;
-       vboxArray mediumAttachments = VBOX_ARRAY_INITIALIZER;
+#else /* VBOX_API_VERSION >= 4000000 */
 
-       if (!strCtl)
-           continue;
+static nsresult
+_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine)
+{
+    return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write);
+}
 
-       strCtl->vtbl->GetName(strCtl, &strCtlName);
-       vboxArrayGetWithPtrArg(&mediumAttachments, machine,
-                              machine->vtbl->GetMediumAttachmentsOfController,
-                              strCtlName);
+static nsresult
+_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine)
+{
+    return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared);
+}
 
-       for (j = 0; j < mediumAttachments.count; j++) {
-           IMediumAttachment *medAtt = mediumAttachments.items[j];
-           PRInt32 port = ~0U;
-           PRInt32 device = ~0U;
+static nsresult
+_sessionClose(ISession *session)
+{
+    return session->vtbl->UnlockMachine(session);
+}
 
-           if (!medAtt)
-               continue;
+#endif /* VBOX_API_VERSION >= 4000000 */
 
-           medAtt->vtbl->GetPort(medAtt, &port);
-           medAtt->vtbl->GetDevice(medAtt, &device);
+static nsresult
+_sessionGetConsole(ISession *session, IConsole **console)
+{
+    return session->vtbl->GetConsole(session, console);
+}
 
-           if ((port != ~0U) && (device != ~0U)) {
-               machine->vtbl->DetachDevice(machine,
-                                           strCtlName,
-                                           port,
-                                           device);
-           }
-       }
-       vboxArrayRelease(&storageControllers);
-       machine->vtbl->RemoveStorageController(machine, strCtlName);
-       VBOX_UTF16_FREE(strCtlName);
-   }
-   vboxArrayRelease(&storageControllers);
+static nsresult
+_sessionGetMachine(ISession *session, IMachine **machine)
+{
+    return session->vtbl->GetMachine(session, machine);
+}
+
+static nsresult
+_consoleSaveState(IConsole *console, IProgress **progress)
+{
+    return console->vtbl->SaveState(console, progress);
+}
+
+static nsresult
+_progressWaitForCompletion(IProgress *progress, PRInt32 timeout)
+{
+    return progress->vtbl->WaitForCompletion(progress, timeout);
+}
+
+static nsresult
+_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode)
+{
+#if VBOX_API_VERSION == 2002000
+    return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode);
+#else /* VBOX_API_VERSION != 2002000 */
+    return progress->vtbl->GetResultCode(progress, &resultCode->resultCode);
+#endif /* VBOX_API_VERSION != 2002000 */
+}
+
+static nsresult
+_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount)
+{
+    return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount);
 }
-# endif /* VBOX_API_VERSION >= 3001000 */
 
 static nsresult
-_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine)
+_systemPropertiesGetMaxBootPosition(ISystemProperties *systemProperties, PRUint32 *maxBootPosition)
 {
-    return data->vboxObj->vtbl->UnregisterMachine(data->vboxObj, IID_MEMBER(value), machine);
+    return systemProperties->vtbl->GetMaxBootPosition(systemProperties, maxBootPosition);
 }
 
-static void
-_deleteConfig(IMachine *machine)
+static nsresult
+_systemPropertiesGetMaxNetworkAdapters(ISystemProperties *systemProperties, PRUint32 chipset ATTRIBUTE_UNUSED,
+                                       PRUint32 *maxNetworkAdapters)
 {
-    machine->vtbl->DeleteSettings(machine);
+#if VBOX_API_VERSION < 4001000
+        return systemProperties->vtbl->GetNetworkAdapterCount(systemProperties,
+                                                              maxNetworkAdapters);
+#else  /* VBOX_API_VERSION >= 4000000 */
+        return systemProperties->vtbl->GetMaxNetworkAdapters(systemProperties, chipset,
+                                                             maxNetworkAdapters);
+#endif /* VBOX_API_VERSION >= 4000000 */
 }
 
-#else /* VBOX_API_VERSION >= 4000000 */
-
-static void
-_detachDevices(vboxGlobalData *data ATTRIBUTE_UNUSED,
-               IMachine *machine ATTRIBUTE_UNUSED,
-               PRUnichar *hddcnameUtf16 ATTRIBUTE_UNUSED)
+static nsresult
+_systemPropertiesGetSerialPortCount(ISystemProperties *systemProperties, PRUint32 *SerialPortCount)
 {
-    vboxUnsupported();
+    return systemProperties->vtbl->GetSerialPortCount(systemProperties, SerialPortCount);
 }
 
 static nsresult
-_unregisterMachine(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine)
+_systemPropertiesGetParallelPortCount(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount)
 {
-    nsresult rc;
-    vboxArray media = VBOX_ARRAY_INITIALIZER;
-    rc = VBOX_OBJECT_GET_MACHINE(IID_MEMBER(value), machine);
-    if (NS_FAILED(rc)) {
-        virReportError(VIR_ERR_NO_DOMAIN, "%s",
-                       _("no domain with matching uuid"));
-        return rc;
-    }
+    return systemProperties->vtbl->GetParallelPortCount(systemProperties, ParallelPortCount);
+}
 
-    /* We're not interested in the array returned by the Unregister method,
-     * but in the side effect of unregistering the virtual machine. In order
-     * to call the Unregister method correctly we need to use the vboxArray
-     * wrapper here. */
-    rc = vboxArrayGetWithUintArg(&media, *machine, (*machine)->vtbl->Unregister,
-                                 CleanupMode_DetachAllReturnNone);
-    vboxArrayUnalloc(&media);
-    return rc;
+#if VBOX_API_VERSION >= 3001000
+static nsresult
+_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties, PRUint32 bus,
+                                              PRUint32 *maxPortCount)
+{
+    return systemProperties->vtbl->GetMaxPortCountForStorageBus(systemProperties, bus, maxPortCount);
 }
 
-static void
-_deleteConfig(IMachine *machine)
+static nsresult
+_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties,
+                                                   PRUint32 bus, PRUint32 *maxDevicesPerPort)
 {
-    IProgress *progress = NULL;
+    return systemProperties->vtbl->GetMaxDevicesPerPortForStorageBus(systemProperties,
+                                                                     bus, maxDevicesPerPort);
+}
+#else /* VBOX_API_VERSION < 3001000 */
+static nsresult
+_systemPropertiesGetMaxPortCountForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED,
+                                              PRUint32 bus ATTRIBUTE_UNUSED,
+                                              PRUint32 *maxPortCount ATTRIBUTE_UNUSED)
+{
+    vboxUnsupported();
+    return 0;
+}
 
-    /* The IMachine Delete method takes an array of IMedium items to be
-     * deleted along with the virtual machine. We just want to pass an
-     * empty array. But instead of adding a full vboxArraySetWithReturn to
-     * the glue layer (in order to handle the required signature of the
-     * Delete method) we use a local solution here. */
-# ifdef WIN32
-    SAFEARRAY *safeArray = NULL;
-    typedef HRESULT __stdcall (*IMachine_Delete)(IMachine *self,
-                                                 SAFEARRAY **media,
-                                                 IProgress **progress);
+static nsresult
+_systemPropertiesGetMaxDevicesPerPortForStorageBus(ISystemProperties *systemProperties ATTRIBUTE_UNUSED,
+                                                   PRUint32 bus ATTRIBUTE_UNUSED,
+                                                   PRUint32 *maxDevicesPerPort ATTRIBUTE_UNUSED)
+{
+    vboxUnsupported();
+    return 0;
+}
+#endif
 
-#  if VBOX_API_VERSION < 4003000
-    ((IMachine_Delete)machine->vtbl->Delete)(machine, &safeArray, &progress);
-#  else
-    ((IMachine_Delete)machine->vtbl->DeleteConfig)(machine, &safeArray, &progress);
-#  endif
-# else
-    /* XPCOM doesn't like NULL as an array, even when the array size is 0.
-     * Instead pass it a dummy array to avoid passing NULL. */
-    IMedium *array[] = { NULL };
-#  if VBOX_API_VERSION < 4003000
-    machine->vtbl->Delete(machine, 0, array, &progress);
-#  else
-    machine->vtbl->DeleteConfig(machine, 0, array, &progress);
-#  endif
-# endif
-    if (progress != NULL) {
-        progress->vtbl->WaitForCompletion(progress, -1);
-        VBOX_RELEASE(progress);
-    }
+static nsresult
+_biosSettingsSetACPIEnabled(IBIOSSettings *bios, PRBool ACPIEnabled)
+{
+    return bios->vtbl->SetACPIEnabled(bios, ACPIEnabled);
 }
 
-#endif /* VBOX_API_VERSION >= 4000000 */
+static nsresult
+_biosSettingsSetIOAPICEnabled(IBIOSSettings *bios, PRBool IOAPICEnabled)
+{
+    return bios->vtbl->SetIOAPICEnabled(bios, IOAPICEnabled);
+}
 
-static void _pfnUninitialize(vboxGlobalData *data)
+static nsresult
+_audioAdapterSetEnabled(IAudioAdapter *audioAdapter, PRBool enabled)
 {
-    if (data->pFuncs)
-        data->pFuncs->pfnComUninitialize();
+    return audioAdapter->vtbl->SetEnabled(audioAdapter, enabled);
 }
 
-static void _pfnComUnallocMem(PCVBOXXPCOM pFuncs, void *pv)
+static nsresult
+_audioAdapterSetAudioController(IAudioAdapter *audioAdapter, PRUint32 audioController)
 {
-    pFuncs->pfnComUnallocMem(pv);
+    return audioAdapter->vtbl->SetAudioController(audioAdapter, audioController);
 }
 
-static void _pfnUtf16Free(PCVBOXXPCOM pFuncs, PRUnichar *pwszString)
+static nsresult
+_networkAdapterSetEnabled(INetworkAdapter *adapter, PRBool enabled)
 {
-    pFuncs->pfnUtf16Free(pwszString);
+    return adapter->vtbl->SetEnabled(adapter, enabled);
 }
 
-static void _pfnUtf8Free(PCVBOXXPCOM pFuncs, char *pszString)
+static nsresult
+_networkAdapterSetAdapterType(INetworkAdapter *adapter, PRUint32 adapterType)
 {
-    pFuncs->pfnUtf8Free(pszString);
+    return adapter->vtbl->SetAdapterType(adapter, adapterType);
 }
 
-static int _pfnUtf16ToUtf8(PCVBOXXPCOM pFuncs, const PRUnichar *pwszString, char **ppszString)
+static nsresult
+_networkAdapterSetInternalNetwork(INetworkAdapter *adapter, PRUnichar *internalNetwork)
 {
-    return pFuncs->pfnUtf16ToUtf8(pwszString, ppszString);
+    return adapter->vtbl->SetInternalNetwork(adapter, internalNetwork);
 }
 
-static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString)
+static nsresult
+_networkAdapterSetMACAddress(INetworkAdapter *adapter, PRUnichar *MACAddress)
 {
-    return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString);
+    return adapter->vtbl->SetMACAddress(adapter, MACAddress);
 }
 
-#if VBOX_API_VERSION == 2002000
+#if VBOX_API_VERSION < 4001000
 
-static void _vboxIIDInitialize(vboxIIDUnion *iidu)
+static nsresult
+_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *hostInterface)
 {
-    memset(iidu, 0, sizeof(vboxIIDUnion));
+    return adapter->vtbl->SetHostInterface(adapter, hostInterface);
 }
 
-static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu)
+static nsresult
+_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface)
 {
-# ifdef WIN32
-    DEBUGUUID(msg, (nsID *)&IID_MEMBER(value));
-# else /* !WIN32 */
-    DEBUGUUID(msg, IID_MEMBER(value));
-# endif /* !WIN32 */
+    return adapter->vtbl->SetHostInterface(adapter, hostOnlyInterface);
 }
 
-#else /* VBOX_API_VERSION != 2002000 */
-
-static void _vboxIIDInitialize(vboxIIDUnion *iidu)
+static nsresult
+_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter)
 {
-    memset(iidu, 0, sizeof(vboxIIDUnion));
-    IID_MEMBER(owner) = true;
+    return adapter->vtbl->AttachToBridgedInterface(adapter);
 }
 
-static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu)
+static nsresult
+_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter)
 {
-    DEBUGPRUnichar(msg, IID_MEMBER(value));
+    return adapter->vtbl->AttachToInternalNetwork(adapter);
 }
 
-#endif /* VBOX_API_VERSION != 2002000 */
+static nsresult
+_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter)
+{
+    return adapter->vtbl->AttachToHostOnlyInterface(adapter);
+}
 
-static void* _handleGetMachines(IVirtualBox *vboxObj)
+static nsresult
+_networkAdapterAttachToNAT(INetworkAdapter *adapter)
 {
-    return vboxObj->vtbl->GetMachines;
+    return adapter->vtbl->AttachToNAT(adapter);
 }
 
-static nsresult _nsisupportsRelease(nsISupports *nsi)
+#else /* VBOX_API_VERSION >= 4001000 */
+
+static nsresult
+_networkAdapterSetBridgedInterface(INetworkAdapter *adapter, PRUnichar *bridgedInterface)
 {
-    return nsi->vtbl->Release(nsi);
+    return adapter->vtbl->SetBridgedInterface(adapter, bridgedInterface);
 }
 
 static nsresult
-_virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16)
+_networkAdapterSetHostOnlyInterface(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface)
 {
-    return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16);
+    return adapter->vtbl->SetHostOnlyInterface(adapter, hostOnlyInterface);
 }
 
-#if VBOX_API_VERSION < 4000000
+static nsresult
+_networkAdapterAttachToBridgedInterface(INetworkAdapter *adapter)
+{
+    return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Bridged);
+}
 
 static nsresult
-_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine)
+_networkAdapterAttachToInternalNetwork(INetworkAdapter *adapter)
 {
-    return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine);
+    return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_Internal);
 }
 
-#else /* VBOX_API_VERSION >= 4000000 */
+static nsresult
+_networkAdapterAttachToHostOnlyInterface(INetworkAdapter *adapter)
+{
+    return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_HostOnly);
+}
 
 static nsresult
-_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine)
+_networkAdapterAttachToNAT(INetworkAdapter *adapter)
 {
-    return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine);
+    return adapter->vtbl->SetAttachmentType(adapter, NetworkAttachmentType_NAT);
 }
 
-#endif /* VBOX_API_VERSION >= 4000000 */
+#endif /* VBOX_API_VERSION >= 4001000 */
 
 static nsresult
-_virtualboxGetSystemProperties(IVirtualBox *vboxObj, ISystemProperties **systemProperties)
+_serialPortSetEnabled(ISerialPort *port, PRBool enabled)
 {
-    return vboxObj->vtbl->GetSystemProperties(vboxObj, systemProperties);
+    return port->vtbl->SetEnabled(port, enabled);
 }
 
 static nsresult
-_machineGetAccessible(IMachine *machine, PRBool *isAccessible)
+_serialPortSetPath(ISerialPort *port, PRUnichar *path)
 {
-    return machine->vtbl->GetAccessible(machine, isAccessible);
+    return port->vtbl->SetPath(port, path);
 }
 
 static nsresult
-_machineGetState(IMachine *machine, PRUint32 *state)
+_serialPortSetIRQ(ISerialPort *port, PRUint32 IRQ)
 {
-    return machine->vtbl->GetState(machine, state);
+    return port->vtbl->SetIRQ(port, IRQ);
 }
 
 static nsresult
-_machineGetName(IMachine *machine, PRUnichar **name)
+_serialPortSetIOBase(ISerialPort *port, PRUint32 IOBase)
 {
-    return machine->vtbl->GetName(machine, name);
+    return port->vtbl->SetIOBase(port, IOBase);
 }
 
 static nsresult
-_machineGetId(IMachine *machine, vboxIIDUnion *iidu)
+_serialPortSetHostMode(ISerialPort *port, PRUint32 hostMode)
 {
-    return machine->vtbl->GetId(machine, &IID_MEMBER(value));
+    return port->vtbl->SetHostMode(port, hostMode);
 }
 
 static nsresult
-_machineSaveSettings(IMachine *machine)
+_parallelPortSetEnabled(IParallelPort *port, PRBool enabled)
 {
-    return machine->vtbl->SaveSettings(machine);
+    return port->vtbl->SetEnabled(port, enabled);
 }
 
-#if VBOX_API_VERSION < 4000000
-
 static nsresult
-_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED)
+_parallelPortSetPath(IParallelPort *port, PRUnichar *path)
 {
-    return data->vboxObj->vtbl->OpenSession(data->vboxObj, data->vboxSession, IID_MEMBER(value));
+    return port->vtbl->SetPath(port, path);
 }
 
 static nsresult
-_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED)
+_parallelPortSetIRQ(IParallelPort *port, PRUint32 IRQ)
 {
-    return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value));
+    return port->vtbl->SetIRQ(port, IRQ);
 }
 
 static nsresult
-_sessionClose(ISession *session)
+_parallelPortSetIOBase(IParallelPort *port, PRUint32 IOBase)
 {
-    return session->vtbl->Close(session);
+    return port->vtbl->SetIOBase(port, IOBase);
 }
 
-#else /* VBOX_API_VERSION >= 4000000 */
+static nsresult
+_vrdxServerSetEnabled(IVRDxServer *VRDxServer, PRBool enabled)
+{
+    return VRDxServer->vtbl->SetEnabled(VRDxServer, enabled);
+}
 
 static nsresult
-_sessionOpen(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine)
+_vrdxServerSetPorts(vboxGlobalData *data ATTRIBUTE_UNUSED,
+                    IVRDxServer *VRDxServer, virDomainGraphicsDefPtr graphics)
 {
-    return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Write);
+    nsresult rc = 0;
+#if VBOX_API_VERSION < 3001000
+    if (graphics->data.rdp.port) {
+        rc = VRDxServer->vtbl->SetPort(VRDxServer,
+                                       graphics->data.rdp.port);
+        VIR_DEBUG("VRDP Port changed to: %d",
+                  graphics->data.rdp.port);
+    } else if (graphics->data.rdp.autoport) {
+        /* Setting the port to 0 will reset its value to
+         * the default one which is 3389 currently
+         */
+        rc = VRDxServer->vtbl->SetPort(VRDxServer, 0);
+        VIR_DEBUG("VRDP Port changed to default, which is 3389 currently");
+    }
+#elif VBOX_API_VERSION < 4000000 /* 3001000 <= VBOX_API_VERSION < 4000000 */
+    PRUnichar *portUtf16 = NULL;
+    portUtf16 = PRUnicharFromInt(graphics->data.rdp.port);
+    rc = VRDxServer->vtbl->SetPorts(VRDxServer, portUtf16);
+    VBOX_UTF16_FREE(portUtf16);
+#else /* VBOX_API_VERSION >= 4000000 */
+    PRUnichar *VRDEPortsKey = NULL;
+    PRUnichar *VRDEPortsValue = NULL;
+    VBOX_UTF8_TO_UTF16("TCP/Ports", &VRDEPortsKey);
+    VRDEPortsValue = PRUnicharFromInt(graphics->data.rdp.port);
+    rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, VRDEPortsKey,
+                                           VRDEPortsValue);
+    VBOX_UTF16_FREE(VRDEPortsKey);
+    VBOX_UTF16_FREE(VRDEPortsValue);
+#endif /* VBOX_API_VERSION >= 4000000 */
+    return rc;
 }
 
 static nsresult
-_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine)
+_vrdxServerSetReuseSingleConnection(IVRDxServer *VRDxServer, PRBool enabled)
 {
-    return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared);
+    return VRDxServer->vtbl->SetReuseSingleConnection(VRDxServer, enabled);
 }
 
 static nsresult
-_sessionClose(ISession *session)
+_vrdxServerSetAllowMultiConnection(IVRDxServer *VRDxServer, PRBool enabled)
 {
-    return session->vtbl->UnlockMachine(session);
+    return VRDxServer->vtbl->SetAllowMultiConnection(VRDxServer, enabled);
 }
 
+static nsresult
+_vrdxServerSetNetAddress(vboxGlobalData *data ATTRIBUTE_UNUSED,
+                         IVRDxServer *VRDxServer, PRUnichar *netAddress)
+{
+#if VBOX_API_VERSION < 4000000
+    return VRDxServer->vtbl->SetNetAddress(VRDxServer,
+                                           netAddress);
+#else /* VBOX_API_VERSION >= 4000000 */
+    PRUnichar *netAddressKey = NULL;
+    nsresult rc;
+    VBOX_UTF8_TO_UTF16("TCP/Address", &netAddressKey);
+    rc = VRDxServer->vtbl->SetVRDEProperty(VRDxServer, netAddressKey,
+                                           netAddress);
+    VBOX_UTF16_FREE(netAddressKey);
+    return rc;
 #endif /* VBOX_API_VERSION >= 4000000 */
+}
 
 static nsresult
-_sessionGetConsole(ISession *session, IConsole **console)
+_usbCommonEnable(IUSBCommon *USBCommon ATTRIBUTE_UNUSED)
 {
-    return session->vtbl->GetConsole(session, console);
+    nsresult rc = 0;
+#if VBOX_API_VERSION < 4003000
+    USBCommon->vtbl->SetEnabled(USBCommon, 1);
+# if VBOX_API_VERSION < 4002000
+    rc = USBCommon->vtbl->SetEnabledEhci(USBCommon, 1);
+# else /* VBOX_API_VERSION >= 4002000 */
+    rc = USBCommon->vtbl->SetEnabledEHCI(USBCommon, 1);
+# endif /* VBOX_API_VERSION >= 4002000 */
+#endif /* VBOX_API_VERSION >= 4003000 */
+    /* We don't need to set usb enabled for vbox 4.3 and later */
+    return rc;
 }
 
 static nsresult
-_sessionGetMachine(ISession *session, IMachine **machine)
+_usbCommonCreateDeviceFilter(IUSBCommon *USBCommon, PRUnichar *name,
+                             IUSBDeviceFilter **filter)
 {
-    return session->vtbl->GetMachine(session, machine);
+    return USBCommon->vtbl->CreateDeviceFilter(USBCommon, name, filter);
 }
 
 static nsresult
-_consoleSaveState(IConsole *console, IProgress **progress)
+_usbCommonInsertDeviceFilter(IUSBCommon *USBCommon, PRUint32 position,
+                             IUSBDeviceFilter *filter)
 {
-    return console->vtbl->SaveState(console, progress);
+    return USBCommon->vtbl->InsertDeviceFilter(USBCommon, position, filter);
 }
 
 static nsresult
-_progressWaitForCompletion(IProgress *progress, PRInt32 timeout)
+_usbDeviceFilterSetProductId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId)
 {
-    return progress->vtbl->WaitForCompletion(progress, timeout);
+    return USBDeviceFilter->vtbl->SetProductId(USBDeviceFilter, productId);
 }
 
 static nsresult
-_progressGetResultCode(IProgress *progress, resultCodeUnion *resultCode)
+_usbDeviceFilterSetActive(IUSBDeviceFilter *USBDeviceFilter, PRBool active)
 {
-#if VBOX_API_VERSION == 2002000
-    return progress->vtbl->GetResultCode(progress, &resultCode->uResultCode);
-#else /* VBOX_API_VERSION != 2002000 */
-    return progress->vtbl->GetResultCode(progress, &resultCode->resultCode);
-#endif /* VBOX_API_VERSION != 2002000 */
+    return USBDeviceFilter->vtbl->SetActive(USBDeviceFilter, active);
 }
 
 static nsresult
-_systemPropertiesGetMaxGuestCPUCount(ISystemProperties *systemProperties, PRUint32 *maxCPUCount)
+_usbDeviceFilterSetVendorId(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId)
 {
-    return systemProperties->vtbl->GetMaxGuestCPUCount(systemProperties, maxCPUCount);
+    return USBDeviceFilter->vtbl->SetVendorId(USBDeviceFilter, vendorId);
+}
+
+static nsresult _mediumGetId(IMedium *medium, vboxIIDUnion *iidu)
+{
+    return medium->vtbl->GetId(medium, &IID_MEMBER(value));
+}
+
+static nsresult _mediumRelease(IMedium *medium)
+{
+    return medium->vtbl->nsisupports.Release((nsISupports *)medium);
+}
+
+static nsresult _mediumSetType(IMedium *medium ATTRIBUTE_UNUSED,
+                               PRUint32 type ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION > 3000000
+    return medium->vtbl->SetType(medium, type);
+#else
+    vboxUnsupported();
+    return 0;
+#endif
 }
 
 static bool _machineStateOnline(PRUint32 state)
@@ -11237,13 +10924,37 @@ static vboxUniformedIVirtualBox _UIVirtualBox = {
     .GetVersion = _virtualboxGetVersion,
     .GetMachine = _virtualboxGetMachine,
     .GetSystemProperties = _virtualboxGetSystemProperties,
+    .CreateMachine = _virtualboxCreateMachine,
+    .RegisterMachine = _virtualboxRegisterMachine,
+    .FindMedium = _virtualboxFindMedium,
+    .OpenMedium = _virtualboxOpenMedium,
 };
 
 static vboxUniformedIMachine _UIMachine = {
+    .AddStorageController = _machineAddStorageController,
+    .AttachDevice = _machineAttachDevice,
+    .CreateSharedFolder = _machineCreateSharedFolder,
     .GetAccessible = _machineGetAccessible,
     .GetState = _machineGetState,
     .GetName = _machineGetName,
     .GetId = _machineGetId,
+    .GetBIOSSettings = _machineGetBIOSSettings,
+    .GetAudioAdapter = _machineGetAudioAdapter,
+    .GetNetworkAdapter = _machineGetNetworkAdapter,
+    .GetChipsetType = _machineGetChipsetType,
+    .GetSerialPort = _machineGetSerialPort,
+    .GetParallelPort = _machineGetParallelPort,
+    .GetVRDxServer = _machineGetVRDxServer,
+    .GetUSBCommon = _machineGetUSBCommon,
+    .SetCPUCount = _machineSetCPUCount,
+    .SetMemorySize = _machineSetMemorySize,
+    .SetCPUProperty = _machineSetCPUProperty,
+    .SetBootOrder = _machineSetBootOrder,
+    .SetVRAMSize = _machineSetVRAMSize,
+    .SetMonitorCount = _machineSetMonitorCount,
+    .SetAccelerate3DEnabled = _machineSetAccelerate3DEnabled,
+    .SetAccelerate2DVideoEnabled = _machineSetAccelerate2DVideoEnabled,
+    .SetExtraData = _machineSetExtraData,
     .SaveSettings = _machineSaveSettings,
 };
 
@@ -11266,6 +10977,76 @@ static vboxUniformedIProgress _UIProgress = {
 
 static vboxUniformedISystemProperties _UISystemProperties = {
     .GetMaxGuestCPUCount = _systemPropertiesGetMaxGuestCPUCount,
+    .GetMaxBootPosition = _systemPropertiesGetMaxBootPosition,
+    .GetMaxNetworkAdapters = _systemPropertiesGetMaxNetworkAdapters,
+    .GetSerialPortCount = _systemPropertiesGetSerialPortCount,
+    .GetParallelPortCount = _systemPropertiesGetParallelPortCount,
+    .GetMaxPortCountForStorageBus = _systemPropertiesGetMaxPortCountForStorageBus,
+    .GetMaxDevicesPerPortForStorageBus = _systemPropertiesGetMaxDevicesPerPortForStorageBus,
+};
+
+static vboxUniformedIBIOSSettings _UIBIOSSettings = {
+    .SetACPIEnabled = _biosSettingsSetACPIEnabled,
+    .SetIOAPICEnabled = _biosSettingsSetIOAPICEnabled,
+};
+
+static vboxUniformedIAudioAdapter _UIAudioAdapter = {
+    .SetEnabled = _audioAdapterSetEnabled,
+    .SetAudioController = _audioAdapterSetAudioController,
+};
+
+static vboxUniformedINetworkAdapter _UINetworkAdapter = {
+    .SetEnabled = _networkAdapterSetEnabled,
+    .SetAdapterType = _networkAdapterSetAdapterType,
+    .SetBridgedInterface = _networkAdapterSetBridgedInterface,
+    .SetInternalNetwork = _networkAdapterSetInternalNetwork,
+    .SetHostOnlyInterface = _networkAdapterSetHostOnlyInterface,
+    .SetMACAddress = _networkAdapterSetMACAddress,
+    .AttachToBridgedInterface = _networkAdapterAttachToBridgedInterface,
+    .AttachToInternalNetwork = _networkAdapterAttachToInternalNetwork,
+    .AttachToHostOnlyInterface = _networkAdapterAttachToHostOnlyInterface,
+    .AttachToNAT = _networkAdapterAttachToNAT,
+};
+
+static vboxUniformedISerialPort _UISerialPort = {
+    .SetEnabled = _serialPortSetEnabled,
+    .SetPath = _serialPortSetPath,
+    .SetIRQ = _serialPortSetIRQ,
+    .SetIOBase = _serialPortSetIOBase,
+    .SetHostMode = _serialPortSetHostMode,
+};
+
+static vboxUniformedIParallelPort _UIParallelPort = {
+    .SetEnabled = _parallelPortSetEnabled,
+    .SetPath = _parallelPortSetPath,
+    .SetIRQ = _parallelPortSetIRQ,
+    .SetIOBase = _parallelPortSetIOBase,
+};
+
+static vboxUniformedIVRDxServer _UIVRDxServer = {
+    .SetEnabled = _vrdxServerSetEnabled,
+    .SetPorts = _vrdxServerSetPorts,
+    .SetReuseSingleConnection = _vrdxServerSetReuseSingleConnection,
+    .SetAllowMultiConnection = _vrdxServerSetAllowMultiConnection,
+    .SetNetAddress = _vrdxServerSetNetAddress,
+};
+
+static vboxUniformedIUSBCommon _UIUSBCommon = {
+    .Enable = _usbCommonEnable,
+    .CreateDeviceFilter = _usbCommonCreateDeviceFilter,
+    .InsertDeviceFilter = _usbCommonInsertDeviceFilter,
+};
+
+static vboxUniformedIUSBDeviceFilter _UIUSBDeviceFilter = {
+    .SetProductId = _usbDeviceFilterSetProductId,
+    .SetActive = _usbDeviceFilterSetActive,
+    .SetVendorId = _usbDeviceFilterSetVendorId,
+};
+
+static vboxUniformedIMedium _UIMedium = {
+    .GetId = _mediumGetId,
+    .Release = _mediumRelease,
+    .SetType = _mediumSetType,
 };
 
 static uniformedMachineStateChecker _machineStateChecker = {
@@ -11281,6 +11062,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
     pVBoxAPI->detachDevices = _detachDevices;
     pVBoxAPI->unregisterMachine = _unregisterMachine;
     pVBoxAPI->deleteConfig = _deleteConfig;
+    pVBoxAPI->vboxAttachDrivesOld = _vboxAttachDrivesOld;
     pVBoxAPI->UPFN = _UPFN;
     pVBoxAPI->UIID = _UIID;
     pVBoxAPI->UArray = _UArray;
@@ -11291,6 +11073,15 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
     pVBoxAPI->UIConsole = _UIConsole;
     pVBoxAPI->UIProgress = _UIProgress;
     pVBoxAPI->UISystemProperties = _UISystemProperties;
+    pVBoxAPI->UIBIOSSettings = _UIBIOSSettings;
+    pVBoxAPI->UIAudioAdapter = _UIAudioAdapter;
+    pVBoxAPI->UINetworkAdapter = _UINetworkAdapter;
+    pVBoxAPI->UISerialPort = _UISerialPort;
+    pVBoxAPI->UIParallelPort = _UIParallelPort;
+    pVBoxAPI->UIVRDxServer = _UIVRDxServer;
+    pVBoxAPI->UIUSBCommon = _UIUSBCommon;
+    pVBoxAPI->UIUSBDeviceFilter = _UIUSBDeviceFilter;
+    pVBoxAPI->UIMedium = _UIMedium;
     pVBoxAPI->machineStateChecker = _machineStateChecker;
 
 #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
@@ -11309,10 +11100,24 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
     /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */
     pVBoxAPI->getMachineForSession = 1;
     pVBoxAPI->detachDevicesExplicitly = 0;
+    pVBoxAPI->vboxAttachDrivesUseOld = 0;
 #else /* VBOX_API_VERSION < 4000000 */
     pVBoxAPI->getMachineForSession = 0;
     pVBoxAPI->detachDevicesExplicitly = 1;
+    pVBoxAPI->vboxAttachDrivesUseOld = 1;
 #endif /* VBOX_API_VERSION < 4000000 */
+
+#if VBOX_API_VERSION >= 4001000
+    pVBoxAPI->chipsetType = 1;
+#else /* VBOX_API_VERSION < 4001000 */
+    pVBoxAPI->chipsetType = 0;
+#endif /* VBOX_API_VERSION < 4001000 */
+
+#if VBOX_API_VERSION >= 3001000
+    pVBoxAPI->accelerate2DVideo = 1;
+#else /* VBOX_API_VERSION < 3001000 */
+    pVBoxAPI->accelerate2DVideo = 0;
+#endif /* VBOX_API_VERSION < 3001000 */
 }
 
 /**
diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h
index 01b91fc..439b1ed 100644
--- a/src/vbox/vbox_uniformed_api.h
+++ b/src/vbox/vbox_uniformed_api.h
@@ -180,14 +180,43 @@ typedef struct {
     nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16);
     nsresult (*GetMachine)(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine);
     nsresult (*GetSystemProperties)(IVirtualBox *vboxObj, ISystemProperties **systemProperties);
+    nsresult (*CreateMachine)(vboxGlobalData *data, virDomainDefPtr def, IMachine **machine, char *uuidstr);
+    nsresult (*RegisterMachine)(IVirtualBox *vboxObj, IMachine *machine);
+    nsresult (*FindMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium);
+    nsresult (*OpenMedium)(IVirtualBox *vboxObj, PRUnichar *location, PRUint32 deviceType, PRUint32 accessMode, IMedium **medium);
 } vboxUniformedIVirtualBox;
 
 /* Functions for IMachine */
 typedef struct {
+    nsresult (*AddStorageController)(IMachine *machine, PRUnichar *name,
+        PRUint32 connectionType, IStorageController **controller);
+    nsresult (*AttachDevice)(IMachine *machine, PRUnichar *name,
+                             PRInt32 controllerPort, PRInt32 device,
+                             PRUint32 type, IMedium *medium);
+    nsresult (*CreateSharedFolder)(IMachine *machine, PRUnichar *name,
+                                   PRUnichar *hostPath, PRBool writable,
+                                   PRBool automount);
     nsresult (*GetAccessible)(IMachine *machine, PRBool *isAccessible);
     nsresult (*GetState)(IMachine *machine, PRUint32 *state);
     nsresult (*GetName)(IMachine *machine, PRUnichar **name);
     nsresult (*GetId)(IMachine *machine, vboxIIDUnion *iidu);
+    nsresult (*GetBIOSSettings)(IMachine *machine, IBIOSSettings **bios);
+    nsresult (*GetAudioAdapter)(IMachine *machine, IAudioAdapter **audioAdapter);
+    nsresult (*GetNetworkAdapter)(IMachine *machine, PRUint32 slot, INetworkAdapter **adapter);
+    nsresult (*GetChipsetType)(IMachine *machine, PRUint32 *chipsetType);
+    nsresult (*GetSerialPort)(IMachine *machine, PRUint32 slot, ISerialPort **port);
+    nsresult (*GetParallelPort)(IMachine *machine, PRUint32 slot, IParallelPort **port);
+    nsresult (*GetVRDxServer)(IMachine *machine, IVRDxServer **VRDxServer);
+    nsresult (*GetUSBCommon)(IMachine *machine, IUSBCommon **USBCommon);
+    nsresult (*SetCPUCount)(IMachine *machine, PRUint32 CPUCount);
+    nsresult (*SetMemorySize)(IMachine *machine, PRUint32 memorySize);
+    nsresult (*SetCPUProperty)(IMachine *machine, PRUint32 property, PRBool value);
+    nsresult (*SetBootOrder)(IMachine *machine, PRUint32 position, PRUint32 device);
+    nsresult (*SetVRAMSize)(IMachine *machine, PRUint32 VRAMSize);
+    nsresult (*SetMonitorCount)(IMachine *machine, PRUint32 monitorCount);
+    nsresult (*SetAccelerate3DEnabled)(IMachine *machine, PRBool accelerate3DEnabled);
+    nsresult (*SetAccelerate2DVideoEnabled)(IMachine *machine, PRBool accelerate2DVideoEnabled);
+    nsresult (*SetExtraData)(IMachine *machine, PRUnichar *key, PRUnichar *value);
     nsresult (*SaveSettings)(IMachine *machine);
 } vboxUniformedIMachine;
 
@@ -214,8 +243,93 @@ typedef struct {
 /* Functions for ISystemProperties */
 typedef struct {
     nsresult (*GetMaxGuestCPUCount)(ISystemProperties *systemProperties, PRUint32 *maxCPUCount);
+    nsresult (*GetMaxBootPosition)(ISystemProperties *systemProperties, PRUint32 *maxBootPosition);
+    nsresult (*GetMaxNetworkAdapters)(ISystemProperties *systemProperties, PRUint32 chipset,
+                                      PRUint32 *maxNetworkAdapters);
+    nsresult (*GetSerialPortCount)(ISystemProperties *systemProperties, PRUint32 *SerialPortCount);
+    nsresult (*GetParallelPortCount)(ISystemProperties *systemProperties, PRUint32 *ParallelPortCount);
+    nsresult (*GetMaxPortCountForStorageBus)(ISystemProperties *systemProperties, PRUint32 bus,
+                                             PRUint32 *maxPortCount);
+    nsresult (*GetMaxDevicesPerPortForStorageBus)(ISystemProperties *systemProperties,
+                                                  PRUint32 bus, PRUint32 *maxDevicesPerPort);
 } vboxUniformedISystemProperties;
 
+/* Functions for IBIOSSettings */
+typedef struct {
+    nsresult (*SetACPIEnabled)(IBIOSSettings *bios, PRBool ACPIEnabled);
+    nsresult (*SetIOAPICEnabled)(IBIOSSettings *bios, PRBool IOAPICEnabled);
+} vboxUniformedIBIOSSettings;
+
+/* Functions for IAudioAdapter */
+typedef struct {
+    nsresult (*SetEnabled)(IAudioAdapter *audioAdapter, PRBool enabled);
+    nsresult (*SetAudioController)(IAudioAdapter *audioAdapter, PRUint32 audioController);
+} vboxUniformedIAudioAdapter;
+
+/* Functions for INetworkAdapter */
+typedef struct {
+    nsresult (*SetEnabled)(INetworkAdapter *adapter, PRBool enabled);
+    nsresult (*SetAdapterType)(INetworkAdapter *adapter, PRUint32 adapterType);
+    nsresult (*SetBridgedInterface)(INetworkAdapter *adapter, PRUnichar *bridgedInterface);
+    nsresult (*SetInternalNetwork)(INetworkAdapter *adapter, PRUnichar *internalNetwork);
+    nsresult (*SetHostOnlyInterface)(INetworkAdapter *adapter, PRUnichar *hostOnlyInterface);
+    nsresult (*SetMACAddress)(INetworkAdapter *adapter, PRUnichar *MACAddress);
+    nsresult (*AttachToBridgedInterface)(INetworkAdapter *adapter);
+    nsresult (*AttachToInternalNetwork)(INetworkAdapter *adapter);
+    nsresult (*AttachToHostOnlyInterface)(INetworkAdapter *adapter);
+    nsresult (*AttachToNAT)(INetworkAdapter *adapter);
+} vboxUniformedINetworkAdapter;
+
+/* Functions for ISerialPort */
+typedef struct {
+    nsresult (*SetEnabled)(ISerialPort *port, PRBool enabled);
+    nsresult (*SetPath)(ISerialPort *port, PRUnichar *path);
+    nsresult (*SetIRQ)(ISerialPort *port, PRUint32 IRQ);
+    nsresult (*SetIOBase)(ISerialPort *port, PRUint32 IOBase);
+    nsresult (*SetHostMode)(ISerialPort *port, PRUint32 hostMode);
+} vboxUniformedISerialPort;
+
+/* Functions for IParallelPort */
+typedef struct {
+    nsresult (*SetEnabled)(IParallelPort *port, PRBool enabled);
+    nsresult (*SetPath)(IParallelPort *port, PRUnichar *path);
+    nsresult (*SetIRQ)(IParallelPort *port, PRUint32 IRQ);
+    nsresult (*SetIOBase)(IParallelPort *port, PRUint32 IOBase);
+} vboxUniformedIParallelPort;
+
+/* Functions for IVRDPServer and IVRDEServer */
+typedef struct {
+    nsresult (*SetEnabled)(IVRDxServer *VRDxServer, PRBool enabled);
+    nsresult (*SetPorts)(vboxGlobalData *data, IVRDxServer *VRDxServer,
+                         virDomainGraphicsDefPtr graphics);
+    nsresult (*SetReuseSingleConnection)(IVRDxServer *VRDxServer, PRBool enabled);
+    nsresult (*SetAllowMultiConnection)(IVRDxServer *VRDxServer, PRBool enabled);
+    nsresult (*SetNetAddress)(vboxGlobalData *data, IVRDxServer *VRDxServer,
+                              PRUnichar *netAddress);
+} vboxUniformedIVRDxServer;
+
+/* Common Functions for IUSBController and IUSBDeviceFilters */
+typedef struct {
+    nsresult (*Enable)(IUSBCommon *USBCommon);
+    nsresult (*CreateDeviceFilter)(IUSBCommon *USBCommon, PRUnichar *name,
+                                   IUSBDeviceFilter **filter);
+    nsresult (*InsertDeviceFilter)(IUSBCommon *USBCommon, PRUint32 position,
+                                   IUSBDeviceFilter *filter);
+} vboxUniformedIUSBCommon;
+
+typedef struct {
+    nsresult (*SetProductId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *productId);
+    nsresult (*SetActive)(IUSBDeviceFilter *USBDeviceFilter, PRBool active);
+    nsresult (*SetVendorId)(IUSBDeviceFilter *USBDeviceFilter, PRUnichar *vendorId);
+} vboxUniformedIUSBDeviceFilter;
+
+/* Functions for IMedium */
+typedef struct {
+    nsresult (*GetId)(IMedium *medium, vboxIIDUnion *iidu);
+    nsresult (*Release)(IMedium *medium);
+    nsresult (*SetType)(IMedium *medium, PRUint32 type);
+} vboxUniformedIMedium;
+
 typedef struct {
     bool (*Online)(PRUint32 state);
 } uniformedMachineStateChecker;
@@ -230,6 +344,7 @@ typedef struct {
     void (*detachDevices)(vboxGlobalData *data, IMachine *machine, PRUnichar *hddcnameUtf16);
     nsresult (*unregisterMachine)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine **machine);
     void (*deleteConfig)(IMachine *machine);
+    void (*vboxAttachDrivesOld)(virDomainDefPtr def, vboxGlobalData *data, IMachine *machine);
     vboxUniformedPFN UPFN;
     vboxUniformedIID UIID;
     vboxUniformedArray UArray;
@@ -240,12 +355,24 @@ typedef struct {
     vboxUniformedIConsole UIConsole;
     vboxUniformedIProgress UIProgress;
     vboxUniformedISystemProperties UISystemProperties;
+    vboxUniformedIBIOSSettings UIBIOSSettings;
+    vboxUniformedIAudioAdapter UIAudioAdapter;
+    vboxUniformedINetworkAdapter UINetworkAdapter;
+    vboxUniformedISerialPort UISerialPort;
+    vboxUniformedIParallelPort UIParallelPort;
+    vboxUniformedIVRDxServer UIVRDxServer;
+    vboxUniformedIUSBCommon UIUSBCommon;
+    vboxUniformedIUSBDeviceFilter UIUSBDeviceFilter;
+    vboxUniformedIMedium UIMedium;
     uniformedMachineStateChecker machineStateChecker;
     /* vbox API features */
     bool domainEventCallbacks;
     bool hasStaticGlobalData;
     bool getMachineForSession;
     bool detachDevicesExplicitly;
+    bool chipsetType;
+    bool accelerate2DVideo;
+    bool vboxAttachDrivesUseOld;
 } vboxUniformedAPI;
 
 /* libvirt API
@@ -269,6 +396,7 @@ int vboxConnectNumOfDomains(virConnectPtr conn);
 virDomainPtr vboxDomainLookupByID(virConnectPtr conn, int id);
 virDomainPtr vboxDomainLookupByUUID(virConnectPtr conn,
                                     const unsigned char *uuid);
+virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml);
 int vboxDomainUndefineFlags(virDomainPtr dom, unsigned int flags);
 
 /* Version specified functions for installing uniformed API */
-- 
1.7.9.5


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]