All vbox objects are child objects from the nsISupports in vbox's C++ API version. Since the CAPI is generated from the C++ API, I kept their relationship here, by the definitations below: typedef struct nsISupports nsISupports; typedef nsISupports IVirtualBox; typedef nsISupports ISession; and so on... So, when calling the API from nsISupports, we don't need to do typecasting, and things work still work well. --- src/vbox/vbox_common.c | 95 ++++++++++++ src/vbox/vbox_common.h | 45 +++++- src/vbox/vbox_tmpl.c | 342 +++++++++++++++++++++++++++++++---------- src/vbox/vbox_uniformed_api.h | 82 ++++++++++ 4 files changed, 477 insertions(+), 87 deletions(-) diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 06f1524..28d8668 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -42,6 +42,9 @@ VIR_LOG_INIT("vbox.vbox_common"); +#define RC_SUCCEEDED(rc) NS_SUCCEEDED(rc.resultCode) +#define RC_FAILED(rc) NS_FAILED(rc.resultCode) + #define VBOX_UTF16_FREE(arg) \ do { \ if (arg) { \ @@ -69,6 +72,31 @@ VIR_LOG_INIT("vbox.vbox_common"); #define VBOX_UTF16_TO_UTF8(arg1, arg2) gVBoxAPI.UPFN.Utf16ToUtf8(data->pFuncs, arg1, arg2) #define VBOX_UTF8_TO_UTF16(arg1, arg2) gVBoxAPI.UPFN.Utf8ToUtf16(data->pFuncs, arg1, arg2) +#define VBOX_RELEASE(arg) \ + do { \ + if (arg) { \ + gVBoxAPI.nsUISupports.Release((void *)arg); \ + (arg) = NULL; \ + } \ + } while (0) + +#define VBOX_OBJECT_CHECK(conn, type, value) \ +vboxGlobalData *data = conn->privateData;\ +type ret = value;\ +if (!data->vboxObj) {\ + return ret;\ +} + +#define vboxIIDUnalloc(iid) gVBoxAPI.UIID.vboxIIDUnalloc(data, iid) +#define vboxIIDToUUID(iid, uuid) gVBoxAPI.UIID.vboxIIDToUUID(data, iid, uuid) +#define vboxIIDFromUUID(iid, uuid) gVBoxAPI.UIID.vboxIIDFromUUID(data, iid, uuid) +#define vboxIIDIsEqual(iid1, iid2) gVBoxAPI.UIID.vboxIIDIsEqual(data, iid1, iid2) +#define DEBUGIID(msg, iid) gVBoxAPI.UIID.DEBUGIID(msg, iid) +#define vboxIIDFromArrayItem(iid, array, idx) \ + gVBoxAPI.UIID.vboxIIDFromArrayItem(data, iid, array, idx) + +#define VBOX_IID_INITIALIZE(iid) gVBoxAPI.UIID.vboxIIDInitialize(iid) + /* global vbox API, used for all common codes. */ static vboxUniformedAPI gVBoxAPI; @@ -103,6 +131,22 @@ int vboxRegisterUniformedAPI(uint32_t uVersion) return 0; } +static int openSessionForMachine(vboxGlobalData *data, const unsigned char *dom_uuid, vboxIIDUnion *iid, + IMachine **machine, bool checkflag) +{ + VBOX_IID_INITIALIZE(iid); + vboxIIDFromUUID(iid, dom_uuid); + if (!checkflag || gVBoxAPI.getMachineForSession) { + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + if (NS_FAILED(gVBoxAPI.UIVirtualBox.GetMachine(data->vboxObj, iid, machine))) { + virReportError(VIR_ERR_NO_DOMAIN, "%s", + _("no domain with matching uuid")); + return -1; + } + } + return 0; +} + static virDomainDefParserConfig vboxDomainDefParserConfig = { .macPrefix = { 0x08, 0x00, 0x27 }, }; @@ -300,3 +344,54 @@ int vboxConnectClose(virConnectPtr conn) return 0; } + +int +vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) +{ + VBOX_OBJECT_CHECK(dom->conn, int, -1); + IConsole *console = NULL; + vboxIIDUnion iid; + IMachine *machine = NULL; + IProgress *progress = NULL; + resultCodeUnion resultCode; + nsresult rc; + + /* VirtualBox currently doesn't support saving to a file + * at a location other then the machine folder and thus + * setting path to ATTRIBUTE_UNUSED for now, will change + * this behaviour once get the VirtualBox API in right + * shape to do this + */ + + /* Open a Session for the machine */ + if (openSessionForMachine(data, dom->uuid, &iid, &machine, true) < 0) + goto cleanup; + + rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine); + if (NS_FAILED(rc)) + goto cleanup; + + rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console); + if (NS_FAILED(rc) || !console) + goto freeSession; + + rc = gVBoxAPI.UIConsole.SaveState(console, &progress); + if (!progress) + goto freeSession; + + gVBoxAPI.UIProgress.WaitForCompletion(progress, -1); + gVBoxAPI.UIProgress.GetResultCode(progress, &resultCode); + if (RC_SUCCEEDED(resultCode)) + ret = 0; + + freeSession: + gVBoxAPI.UISession.Close(data->vboxSession); + + cleanup: + DEBUGIID("UUID of machine being saved:", &iid); + VBOX_RELEASE(machine); + VBOX_RELEASE(console); + VBOX_RELEASE(progress); + vboxIIDUnalloc(&iid); + return ret; +} diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h index 61f410d..800e7cc 100644 --- a/src/vbox/vbox_common.h +++ b/src/vbox/vbox_common.h @@ -121,10 +121,51 @@ typedef PRUint32 nsresult; # define NS_FAILED(_nsresult) (NS_UNLIKELY((_nsresult) & 0x80000000)) # define NS_SUCCEEDED(_nsresult) (NS_LIKELY(!((_nsresult) & 0x80000000))) +/** + * An "interface id" which can be used to uniquely identify a given + * interface. + * A "unique identifier". This is modeled after OSF DCE UUIDs. + */ + +struct nsID { + PRUint32 m0; + PRUint16 m1; + PRUint16 m2; + PRUint8 m3[8]; +}; + +typedef struct nsID nsID; +typedef nsID nsIID; + +typedef struct _vboxArray vboxArray; + +# ifdef WIN32 + +struct _vboxArray { + void **items; + size_t count; + void *handle; +}; +# define VBOX_ARRAY_INITIALIZER { NULL, 0, NULL } + +# else /* !WIN32 */ + +struct _vboxArray { + void **items; + size_t count; +}; +# define VBOX_ARRAY_INITIALIZER { NULL, 0 } + +# endif /* !WIN32 */ + /* Simplied definitions in vbox_CAPI_*.h */ typedef void const *PCVBOXXPCOM; -typedef void IVirtualBox; -typedef void ISession; +typedef struct nsISupports nsISupports; +typedef nsISupports IVirtualBox; +typedef nsISupports ISession; +typedef nsISupports IConsole; +typedef nsISupports IProgress; +typedef nsISupports IMachine; #endif /* VBOX_COMMON_H */ diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 6315a64..0e9b6c8 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -192,7 +192,7 @@ if (strUtf16) {\ #define DEBUGUUID(msg, iid) \ {\ - VIR_DEBUG(msg ": {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",\ + VIR_DEBUG("%s: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", msg,\ (unsigned)(iid)->m0,\ (unsigned)(iid)->m1,\ (unsigned)(iid)->m2,\ @@ -355,12 +355,8 @@ static void nsIDFromChar(nsID *iid, const unsigned char *uuid) typedef struct _vboxIID_v2_x_WIN32 vboxIID; typedef struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; -struct _vboxIID_v2_x_WIN32 { - /* IID is represented by a GUID value. */ - GUID value; -}; - # define VBOX_IID_INITIALIZER { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } +# define IID_MEMBER(name) (iidu->vboxIID_v2_x_WIN32.name) static void vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, @@ -370,12 +366,25 @@ vboxIIDUnalloc_v2_x_WIN32(vboxGlobalData *data ATTRIBUTE_UNUSED, } static void +_vboxIIDUnalloc(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iid ATTRIBUTE_UNUSED) +{ + /* Nothing to free */ +} + +static void vboxIIDToUUID_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid, unsigned char *uuid) { nsIDtoChar(uuid, (nsID *)&iid->value); } static void +_vboxIIDToUUID(vboxGlobalData *data ATTRIBUTE_UNUSED, vboxIIDUnion *iidu, unsigned char *uuid) +{ + vboxIIDToUUID_v2_x_WIN32(&iidu->vboxIID_v2_x_WIN32, uuid); +} + +static void vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, const unsigned char *uuid) { @@ -384,12 +393,25 @@ vboxIIDFromUUID_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, nsIDFromChar((nsID *)&iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x_WIN32(data, &iidu->vboxIID_v2_x_WIN32, uuid); +} + static bool vboxIIDIsEqual_v2_x_WIN32(vboxIID_v2_x_WIN32 *iid1, vboxIID_v2_x_WIN32 *iid2) { return memcmp(&iid1->value, &iid2->value, sizeof(GUID)) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data ATTRIBUTE_UNUSED, vboxIIDUnion *iidu1, vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v2_x_WIN32(&iidu1->vboxIID_v2_x_WIN32, &iidu2->vboxIID_v2_x_WIN32); +} + static void vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, vboxArray *array, int idx) @@ -401,6 +423,13 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, memcpy(&iid->value, &items[idx], sizeof(GUID)); } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v2_x_WIN32(data, &iidu->vboxIID_v2_x_WIN32, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x_WIN32(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x_WIN32(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x_WIN32(data, iid, uuid) @@ -414,17 +443,8 @@ vboxIIDFromArrayItem_v2_x_WIN32(vboxGlobalData *data, vboxIID_v2_x_WIN32 *iid, typedef struct _vboxIID_v2_x vboxIID; typedef struct _vboxIID_v2_x vboxIID_v2_x; -struct _vboxIID_v2_x { - /* IID is represented by a pointer to a nsID. */ - nsID *value; - - /* backing is used in cases where we need to create or copy an IID. - * We cannot allocate memory that can be freed by ComUnallocMem. - * Therefore, we use this stack allocated nsID instead. */ - nsID backing; -}; - # define VBOX_IID_INITIALIZER { NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } } +# define IID_MEMBER(name) (iidu->vboxIID_v2_x.name) static void vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) @@ -441,12 +461,25 @@ vboxIIDUnalloc_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v2_x(data, &iidu->vboxIID_v2_x); +} + +static void vboxIIDToUUID_v2_x(vboxIID_v2_x *iid, unsigned char *uuid) { nsIDtoChar(uuid, iid->value); } static void +_vboxIIDToUUID(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu, unsigned char *uuid) +{ + vboxIIDToUUID_v2_x(&iidu->vboxIID_v2_x, uuid); +} + +static void vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, const unsigned char *uuid) { @@ -458,12 +491,26 @@ vboxIIDFromUUID_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, nsIDFromChar(iid->value, uuid); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v2_x(data, &iidu->vboxIID_v2_x, uuid); +} + static bool vboxIIDIsEqual_v2_x(vboxIID_v2_x *iid1, vboxIID_v2_x *iid2) { return memcmp(iid1->value, iid2->value, sizeof(nsID)) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data ATTRIBUTE_UNUSED, + vboxIIDUnion *iidu1, vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v2_x(&iidu1->vboxIID_v2_x, &iidu2->vboxIID_v2_x); +} + static void vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, vboxArray *array, int idx) @@ -475,6 +522,13 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, memcpy(iid->value, array->items[idx], sizeof(nsID)); } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v2_x(data, &iidu->vboxIID_v2_x, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v2_x(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v2_x(iid, uuid) # define vboxIIDFromUUID(iid, uuid) vboxIIDFromUUID_v2_x(data, iid, uuid) @@ -490,15 +544,8 @@ vboxIIDFromArrayItem_v2_x(vboxGlobalData *data, vboxIID_v2_x *iid, typedef struct _vboxIID_v3_x vboxIID; typedef struct _vboxIID_v3_x vboxIID_v3_x; -struct _vboxIID_v3_x { - /* IID is represented by a UTF-16 encoded UUID in string form. */ - PRUnichar *value; - - /* owner indicates if we own the value and need to free it. */ - bool owner; -}; - # define VBOX_IID_INITIALIZER { NULL, true } +# define IID_MEMBER(name) (iidu->vboxIID_v3_x.name) static void vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) @@ -512,6 +559,12 @@ vboxIIDUnalloc_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid) } static void +_vboxIIDUnalloc(vboxGlobalData *data, vboxIIDUnion *iidu) +{ + vboxIIDUnalloc_v3_x(data, &iidu->vboxIID_v3_x); +} + +static void vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, unsigned char *uuid) { @@ -525,6 +578,13 @@ vboxIIDToUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, } static void +_vboxIIDToUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + unsigned char *uuid) +{ + vboxIIDToUUID_v3_x(data, &iidu->vboxIID_v3_x, uuid); +} + +static void vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, const unsigned char *uuid) { @@ -537,6 +597,13 @@ vboxIIDFromUUID_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, data->pFuncs->pfnUtf8ToUtf16(utf8, &iid->value); } +static void +_vboxIIDFromUUID(vboxGlobalData *data, vboxIIDUnion *iidu, + const unsigned char *uuid) +{ + vboxIIDFromUUID_v3_x(data, &iidu->vboxIID_v3_x, uuid); +} + static bool vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1, vboxIID_v3_x *iid2) @@ -555,6 +622,12 @@ vboxIIDIsEqual_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid1, return memcmp(uuid1, uuid2, VIR_UUID_BUFLEN) == 0; } +static bool +_vboxIIDIsEqual(vboxGlobalData *data, vboxIIDUnion *iidu1, + vboxIIDUnion *iidu2) +{ + return vboxIIDIsEqual_v3_x(data, &iidu1->vboxIID_v3_x, &iidu2->vboxIID_v3_x); +} static void vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, @@ -566,6 +639,13 @@ vboxIIDFromArrayItem_v3_x(vboxGlobalData *data, vboxIID_v3_x *iid, iid->owner = false; } +static void +_vboxIIDFromArrayItem(vboxGlobalData *data, vboxIIDUnion *iidu, + vboxArray *array, int idx) +{ + vboxIIDFromArrayItem_v3_x(data, &iidu->vboxIID_v3_x, array, idx); +} + # define vboxIIDUnalloc(iid) vboxIIDUnalloc_v3_x(data, iid) # define vboxIIDToUUID(iid, uuid) vboxIIDToUUID_v3_x(data, iid, uuid) @@ -1826,67 +1906,6 @@ vboxDomainGetState(virDomainPtr dom, return ret; } -static int vboxDomainSave(virDomainPtr dom, const char *path ATTRIBUTE_UNUSED) -{ - VBOX_OBJECT_CHECK(dom->conn, int, -1); - IConsole *console = NULL; - vboxIID iid = VBOX_IID_INITIALIZER; - IMachine *machine = NULL; - nsresult rc; - - /* VirtualBox currently doesn't support saving to a file - * at a location other then the machine folder and thus - * setting path to ATTRIBUTE_UNUSED for now, will change - * this behaviour once get the VirtualBox API in right - * shape to do this - */ - - /* Open a Session for the machine */ - vboxIIDFromUUID(&iid, dom->uuid); -#if VBOX_API_VERSION >= 4000000 - /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ - rc = VBOX_OBJECT_GET_MACHINE(iid.value, &machine); - if (NS_FAILED(rc)) { - virReportError(VIR_ERR_NO_DOMAIN, "%s", - _("no domain with matching uuid")); - return -1; - } -#endif - - 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) { - IProgress *progress = NULL; - - console->vtbl->SaveState(console, &progress); - - if (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)) { - ret = 0; - } - VBOX_RELEASE(progress); - } - VBOX_RELEASE(console); - } - VBOX_SESSION_CLOSE(); - } - - DEBUGIID("UUID of machine being saved:", iid.value); - - VBOX_RELEASE(machine); - vboxIIDUnalloc(&iid); - return ret; -} - static int vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags) @@ -11303,12 +11322,124 @@ static int _pfnUtf8ToUtf16(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar return pFuncs->pfnUtf8ToUtf16(pszString, ppwszString); } +#if VBOX_API_VERSION == 2002000 + +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 */ +} + +#else /* VBOX_API_VERSION != 2002000 */ + +static void _vboxIIDInitialize(vboxIIDUnion *iidu) +{ + memset(iidu, 0, sizeof(vboxIIDUnion)); + IID_MEMBER(owner) = true; +} + +static void _DEBUGIID(const char *msg, vboxIIDUnion *iidu) +{ + DEBUGPRUnichar(msg, IID_MEMBER(value)); +} + +#endif /* VBOX_API_VERSION != 2002000 */ + +static nsresult _nsisupportsRelease(nsISupports *nsi) +{ + return nsi->vtbl->Release(nsi); +} + static nsresult _virtualboxGetVersion(IVirtualBox *vboxObj, PRUnichar **versionUtf16) { return vboxObj->vtbl->GetVersion(vboxObj, versionUtf16); } +#if VBOX_API_VERSION < 4000000 + +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->GetMachine(vboxObj, IID_MEMBER(value), machine); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_virtualboxGetMachine(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine) +{ + return vboxObj->vtbl->FindMachine(vboxObj, IID_MEMBER(value), machine); +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + +#if VBOX_API_VERSION < 4000000 + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine ATTRIBUTE_UNUSED) +{ + return data->vboxObj->vtbl->OpenExistingSession(data->vboxObj, data->vboxSession, IID_MEMBER(value)); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->Close(session); +} + +#else /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_sessionOpenExisting(vboxGlobalData *data, vboxIIDUnion *iidu ATTRIBUTE_UNUSED, IMachine *machine) +{ + return machine->vtbl->LockMachine(machine, data->vboxSession, LockType_Shared); +} + +static nsresult +_sessionClose(ISession *session) +{ + return session->vtbl->UnlockMachine(session); +} + +#endif /* VBOX_API_VERSION >= 4000000 */ + +static nsresult +_sessionGetConsole(ISession *session, IConsole **console) +{ + return session->vtbl->GetConsole(session, console); +} + +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 vboxUniformedPFN _UPFN = { .Initialize = _pfnInitialize, .Uninitialize = _pfnUninitialize, @@ -11319,8 +11450,38 @@ static vboxUniformedPFN _UPFN = { .Utf8ToUtf16 = _pfnUtf8ToUtf16, }; +static vboxUniformedIID _UIID = { + .vboxIIDInitialize = _vboxIIDInitialize, + .vboxIIDUnalloc = _vboxIIDUnalloc, + .vboxIIDToUUID = _vboxIIDToUUID, + .vboxIIDFromUUID = _vboxIIDFromUUID, + .vboxIIDIsEqual = _vboxIIDIsEqual, + .vboxIIDFromArrayItem = _vboxIIDFromArrayItem, + .DEBUGIID = _DEBUGIID, +}; + +static vboxUniformednsISupports _nsUISupports = { + .Release = _nsisupportsRelease, +}; + static vboxUniformedIVirtualBox _UIVirtualBox = { .GetVersion = _virtualboxGetVersion, + .GetMachine = _virtualboxGetMachine, +}; + +static vboxUniformedISession _UISession = { + .OpenExisting = _sessionOpenExisting, + .GetConsole = _sessionGetConsole, + .Close = _sessionClose, +}; + +static vboxUniformedIConsole _UIConsole = { + .SaveState = _consoleSaveState, +}; + +static vboxUniformedIProgress _UIProgress = { + .WaitForCompletion = _progressWaitForCompletion, + .GetResultCode = _progressGetResultCode, }; void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) @@ -11330,7 +11491,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->initializeDomainEvent = _initializeDomainEvent; pVBoxAPI->registerGlobalData = _registerGlobalData; pVBoxAPI->UPFN = _UPFN; + pVBoxAPI->UIID = _UIID; + pVBoxAPI->nsUISupports = _nsUISupports; pVBoxAPI->UIVirtualBox = _UIVirtualBox; + pVBoxAPI->UISession = _UISession; + pVBoxAPI->UIConsole = _UIConsole; + pVBoxAPI->UIProgress = _UIProgress; #if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000 pVBoxAPI->domainEventCallbacks = 0; @@ -11344,6 +11510,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI) pVBoxAPI->hasStaticGlobalData = 1; #endif /* VBOX_API_VERSION > 2002000 */ +#if VBOX_API_VERSION >= 4000000 + /* Get machine for the call to VBOX_SESSION_OPEN_EXISTING */ + pVBoxAPI->getMachineForSession = 1; +#else /* VBOX_API_VERSION < 4000000 */ + pVBoxAPI->getMachineForSession = 0; +#endif /* VBOX_API_VERSION < 4000000 */ } /** diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h index f424047..8538754 100644 --- a/src/vbox/vbox_uniformed_api.h +++ b/src/vbox/vbox_uniformed_api.h @@ -56,6 +56,46 @@ * */ +/* Extracted define from vbox_tmpl.c */ + +# ifdef WIN32 +struct _vboxIID_v2_x_WIN32 { + /* IID is represented by a GUID value. */ + GUID value; +}; +# endif /* !WIN32 */ + +struct _vboxIID_v2_x { + /* IID is represented by a pointer to a nsID. */ + nsID *value; + + /* backing is used in cases where we need to create or copy an IID. + * We cannot allocate memory that can be freed by ComUnallocMem. + * Therefore, we use this stack allocated nsID instead. */ + nsID backing; +}; + +struct _vboxIID_v3_x { + /* IID is represented by a UTF-16 encoded UUID in string form. */ + PRUnichar *value; + + /* owner indicates if we own the value and need to free it. */ + bool owner; +}; + +typedef union { +# ifdef WIN32 + struct _vboxIID_v2_x_WIN32 vboxIID_v2_x_WIN32; +# endif /* !WIN32 */ + struct _vboxIID_v2_x vboxIID_v2_x; + struct _vboxIID_v3_x vboxIID_v3_x; +} vboxIIDUnion; + +typedef union { + nsresult uResultCode; + PRInt32 resultCode; +} resultCodeUnion; + typedef struct { virMutex lock; unsigned long version; @@ -111,11 +151,46 @@ typedef struct { int (*Utf8ToUtf16)(PCVBOXXPCOM pFuncs, const char *pszString, PRUnichar **ppwszString); } vboxUniformedPFN; +/* Functions for vboxIID */ +typedef struct { + void (*vboxIIDInitialize)(vboxIIDUnion *iidu); + void (*vboxIIDUnalloc)(vboxGlobalData *data, vboxIIDUnion *iidu); + void (*vboxIIDToUUID)(vboxGlobalData *data, vboxIIDUnion *iidu, unsigned char *uuid); + void (*vboxIIDFromUUID)(vboxGlobalData *data, vboxIIDUnion *iidu, const unsigned char *uuid); + bool (*vboxIIDIsEqual)(vboxGlobalData *data, vboxIIDUnion *iidu1, vboxIIDUnion *iidu2); + void (*vboxIIDFromArrayItem)(vboxGlobalData *data, vboxIIDUnion *iidu, vboxArray *array, int idx); + void (*DEBUGIID)(const char *msg, vboxIIDUnion *iidu); +} vboxUniformedIID; + +/* Functions for nsISupports */ +typedef struct { + nsresult (*Release)(nsISupports *nsi); +} vboxUniformednsISupports; + /* Functions for IVirtualBox */ typedef struct { nsresult (*GetVersion)(IVirtualBox *vboxObj, PRUnichar **versionUtf16); + nsresult (*GetMachine)(IVirtualBox *vboxObj, vboxIIDUnion *iidu, IMachine **machine); } vboxUniformedIVirtualBox; +/* Functions for ISession */ +typedef struct { + nsresult (*OpenExisting)(vboxGlobalData *data, vboxIIDUnion *iidu, IMachine *machine); + nsresult (*GetConsole)(ISession *session, IConsole **console); + nsresult (*Close)(ISession *session); +} vboxUniformedISession; + +/* Functions for IConsole */ +typedef struct { + nsresult (*SaveState)(IConsole *console, IProgress **progress); +} vboxUniformedIConsole; + +/* Functions for IProgress */ +typedef struct { + nsresult (*WaitForCompletion)(IProgress *progress, PRInt32 timeout); + nsresult (*GetResultCode)(IProgress *progress, resultCodeUnion *resultCode); +} vboxUniformedIProgress; + typedef struct { /* vbox API version */ uint32_t APIVersion; @@ -124,10 +199,16 @@ typedef struct { int (*initializeDomainEvent)(vboxGlobalData *data); void (*registerGlobalData)(vboxGlobalData *data); vboxUniformedPFN UPFN; + vboxUniformedIID UIID; + vboxUniformednsISupports nsUISupports; vboxUniformedIVirtualBox UIVirtualBox; + vboxUniformedISession UISession; + vboxUniformedIConsole UIConsole; + vboxUniformedIProgress UIProgress; /* vbox API features */ bool domainEventCallbacks; bool hasStaticGlobalData; + bool getMachineForSession; } vboxUniformedAPI; /* libvirt API @@ -138,6 +219,7 @@ virDrvOpenStatus vboxConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags); int vboxConnectClose(virConnectPtr conn); +int vboxDomainSave(virDomainPtr dom, const char *path); /* Version specified functions for installing uniformed API */ void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI); -- 1.7.9.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list