---
src/vbox/vbox_common.c | 130 ++++++++++++++++++++++++++++
src/vbox/vbox_common.h | 1 +
src/vbox/vbox_tmpl.c | 190 ++++++++++++-----------------------------
src/vbox/vbox_uniformed_api.h | 23 ++++-
4 files changed, 208 insertions(+), 136 deletions(-)
diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
index 505f1cd..d3735ac 100644
--- a/src/vbox/vbox_common.c
+++ b/src/vbox/vbox_common.c
@@ -19,6 +19,7 @@
#include <config.h>
#include <unistd.h>
+#include <fcntl.h>
#include "internal.h"
#include "datatypes.h"
@@ -32,6 +33,8 @@
#include "virtime.h"
#include "snapshot_conf.h"
#include "vbox_snapshot_conf.h"
+#include "fdstream.h"
+#include "configmake.h"
#include "vbox_common.h"
#include "vbox_uniformed_api.h"
@@ -7133,3 +7136,130 @@ int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
gVBoxAPI.UISession.Close(data->vboxSession);
return ret;
}
+
+char *
+vboxDomainScreenshot(virDomainPtr dom,
+ virStreamPtr st,
+ unsigned int screen,
+ unsigned int flags)
+{
+ VBOX_OBJECT_CHECK(dom->conn, char *, NULL);
+ IConsole *console = NULL;
+ vboxIIDUnion iid;
+ IMachine *machine = NULL;
+ nsresult rc;
+ char *tmp;
+ int tmp_fd = -1;
+ unsigned int max_screen;
+
+ if (!gVBoxAPI.supportScreenshot) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("virDomainScreenshot don't support for current vbox
version"));
+ return NULL;
+ }
+
+ virCheckFlags(0, NULL);
+
+ if (openSessionForMachine(data, dom->uuid, &iid, &machine, false) < 0)
+ return NULL;
+
+ rc = gVBoxAPI.UIMachine.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 (screen >= max_screen) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("screen ID higher than monitor "
+ "count (%d)"), max_screen);
+ VBOX_RELEASE(machine);
+ return NULL;
+ }
+
+ if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX",
LOCALSTATEDIR) < 0) {
+ VBOX_RELEASE(machine);
+ return NULL;
+ }
+
+ if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
+ virReportSystemError(errno, _("mkostemp(\"%s\") failed"),
tmp);
+ VIR_FREE(tmp);
+ VBOX_RELEASE(machine);
+ return NULL;
+ }
+
+
+ rc = gVBoxAPI.UISession.OpenExisting(data, &iid, machine);
+ if (NS_SUCCEEDED(rc)) {
+ rc = gVBoxAPI.UISession.GetConsole(data->vboxSession, &console);
+ if (NS_SUCCEEDED(rc) && console) {
+ IDisplay *display = NULL;
+
+ gVBoxAPI.UIConsole.GetDisplay(console, &display);
+
+ if (display) {
+ PRUint32 width, height, bitsPerPixel;
+ PRUint32 screenDataSize;
+ PRUint8 *screenData;
+ PRInt32 xOrigin, yOrigin;
+
+ rc = gVBoxAPI.UIDisplay.GetScreenResolution(display, screen,
+ &width, &height,
+ &bitsPerPixel,
+ &xOrigin, &yOrigin);
+
+ if (NS_FAILED(rc) || !width || !height) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("unable to get screen resolution"));
+ goto endjob;
+ }
+
+ rc = gVBoxAPI.UIDisplay.TakeScreenShotPNGToArray(display, screen,
+ width, height,
+ &screenDataSize,
+ &screenData);
+ if (NS_FAILED(rc)) {
+ virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+ _("failed to take screenshot"));
+ goto endjob;
+ }
+
+ if (safewrite(tmp_fd, (char *) screenData,
+ screenDataSize) < 0) {
+ virReportSystemError(errno, _("unable to write data "
+ "to '%s'"), tmp);
+ goto endjob;
+ }
+
+ if (VIR_CLOSE(tmp_fd) < 0) {
+ virReportSystemError(errno, _("unable to close %s"), tmp);
+ goto endjob;
+ }
+
+ if (VIR_STRDUP(ret, "image/png") < 0)
+ goto endjob;
+
+ 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);
+ }
+ gVBoxAPI.UISession.Close(data->vboxSession);
+ }
+
+ VIR_FORCE_CLOSE(tmp_fd);
+ unlink(tmp);
+ VIR_FREE(tmp);
+ VBOX_RELEASE(machine);
+ vboxIIDUnalloc(&iid);
+ return ret;
+}
diff --git a/src/vbox/vbox_common.h b/src/vbox/vbox_common.h
index 15bf8e2..b5a0353 100644
--- a/src/vbox/vbox_common.h
+++ b/src/vbox/vbox_common.h
@@ -301,5 +301,6 @@ typedef nsISupports IMediumAttachment;
typedef nsISupports IStorageController;
typedef nsISupports ISharedFolder;
typedef nsISupports ISnapshot;
+typedef nsISupports IDisplay;
#endif /* VBOX_COMMON_H */
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c
index 044e6d6..82c45ad 100644
--- a/src/vbox/vbox_tmpl.c
+++ b/src/vbox/vbox_tmpl.c
@@ -3732,141 +3732,6 @@ static char *vboxStorageVolGetPath(virStorageVolPtr vol) {
return ret;
}
-#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 (screen >= max_screen) {
- virReportError(VIR_ERR_INVALID_ARG,
- _("screen ID higher than monitor "
- "count (%d)"), max_screen);
- VBOX_RELEASE(machine);
- return NULL;
- }
-
- if (virAsprintf(&tmp, "%s/cache/libvirt/vbox.screendump.XXXXXX",
LOCALSTATEDIR) < 0) {
- VBOX_RELEASE(machine);
- return NULL;
- }
-
- if ((tmp_fd = mkostemp(tmp, O_CLOEXEC)) == -1) {
- virReportSystemError(errno, _("mkostemp(\"%s\") failed"),
tmp);
- VIR_FREE(tmp);
- VBOX_RELEASE(machine);
- return NULL;
- }
-
-
- 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;
-
- console->vtbl->GetDisplay(console, &display);
-
- if (display) {
- PRUint32 width, height, bitsPerPixel;
- PRUint32 screenDataSize;
- PRUint8 *screenData;
-# if VBOX_API_VERSION >= 4003000
- PRInt32 xOrigin, yOrigin;
-# endif
-
- rc = display->vtbl->GetScreenResolution(display, screen,
- &width, &height,
-# if VBOX_API_VERSION < 4003000
- &bitsPerPixel);
-# else
- &bitsPerPixel,
- &xOrigin, &yOrigin);
-# endif
-
- if (NS_FAILED(rc) || !width || !height) {
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
- _("unable to get screen resolution"));
- goto endjob;
- }
-
- 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;
- }
-
- if (safewrite(tmp_fd, (char *) screenData,
- screenDataSize) < 0) {
- virReportSystemError(errno, _("unable to write data "
- "to '%s'"), tmp);
- goto endjob;
- }
-
- if (VIR_CLOSE(tmp_fd) < 0) {
- virReportSystemError(errno, _("unable to close %s"), tmp);
- goto endjob;
- }
-
- if (VIR_STRDUP(ret, "image/png") < 0)
- goto endjob;
-
- 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();
- }
-
- 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
vboxConnectListAllDomains(virConnectPtr conn,
@@ -5474,6 +5339,12 @@ _consoleDeleteSnapshot(IConsole *console, vboxIIDUnion *iidu,
IProgress **progre
}
static nsresult
+_consoleGetDisplay(IConsole *console, IDisplay **display)
+{
+ return console->vtbl->GetDisplay(console, display);
+}
+
+static nsresult
_progressWaitForCompletion(IProgress *progress, PRInt32 timeout)
{
return progress->vtbl->WaitForCompletion(progress, timeout);
@@ -6339,6 +6210,46 @@ _snapshotGetOnline(ISnapshot *snapshot, PRBool *online)
return snapshot->vtbl->GetOnline(snapshot, online);
}
+static nsresult
+_displayGetScreenResolution(IDisplay *display ATTRIBUTE_UNUSED,
+ PRUint32 screenId ATTRIBUTE_UNUSED,
+ PRUint32 *width ATTRIBUTE_UNUSED,
+ PRUint32 *height ATTRIBUTE_UNUSED,
+ PRUint32 *bitsPerPixel ATTRIBUTE_UNUSED,
+ PRInt32 *xOrigin ATTRIBUTE_UNUSED,
+ PRInt32 *yOrigin ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION < 3002000
+ vboxUnsupported();
+ return 0;
+#elif VBOX_API_VERSION < 4003000
+ return display->vtbl->GetScreenResolution(display, screenId, width,
+ height, bitsPerPixel);
+#else /* VBOX_API_VERSION >= 4003000 */
+ return display->vtbl->GetScreenResolution(display, screenId, width,
+ height, bitsPerPixel,
+ xOrigin, yOrigin);
+#endif /* VBOX_API_VERSION >= 4003000 */
+}
+
+static nsresult
+_displayTakeScreenShotPNGToArray(IDisplay *display ATTRIBUTE_UNUSED,
+ PRUint32 screenId ATTRIBUTE_UNUSED,
+ PRUint32 width ATTRIBUTE_UNUSED,
+ PRUint32 height ATTRIBUTE_UNUSED,
+ PRUint32 *screenDataSize ATTRIBUTE_UNUSED,
+ PRUint8** screenData ATTRIBUTE_UNUSED)
+{
+#if VBOX_API_VERSION < 4000000
+ vboxUnsupported();
+ return 0;
+#else /* VBOX_API_VERSION >= 4000000 */
+ return display->vtbl->TakeScreenShotPNGToArray(display, screenId, width,
+ height, screenDataSize,
+ screenData);
+#endif /* VBOX_API_VERSION >= 4000000 */
+}
+
static bool _machineStateOnline(PRUint32 state)
{
return ((state >= MachineState_FirstOnline) &&
@@ -6486,6 +6397,7 @@ static vboxUniformedIConsole _UIConsole = {
.Reset = _consoleReset,
.TakeSnapshot = _consoleTakeSnapshot,
.DeleteSnapshot = _consoleDeleteSnapshot,
+ .GetDisplay = _consoleGetDisplay,
};
static vboxUniformedIProgress _UIProgress = {
@@ -6634,6 +6546,11 @@ static vboxUniformedISnapshot _UISnapshot = {
.GetOnline = _snapshotGetOnline,
};
+static vboxUniformedIDisplay _UIDisplay = {
+ .GetScreenResolution = _displayGetScreenResolution,
+ .TakeScreenShotPNGToArray = _displayTakeScreenShotPNGToArray,
+};
+
static uniformedMachineStateChecker _machineStateChecker = {
.Online = _machineStateOnline,
.Inactive = _machineStateInactive,
@@ -6685,6 +6602,7 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->UIStorageController = _UIStorageController;
pVBoxAPI->UISharedFolder = _UISharedFolder;
pVBoxAPI->UISnapshot = _UISnapshot;
+ pVBoxAPI->UIDisplay = _UIDisplay;
pVBoxAPI->machineStateChecker = _machineStateChecker;
#if VBOX_API_VERSION <= 2002000 || VBOX_API_VERSION >= 4000000
@@ -6704,10 +6622,12 @@ void NAME(InstallUniformedAPI)(vboxUniformedAPI *pVBoxAPI)
pVBoxAPI->getMachineForSession = 1;
pVBoxAPI->detachDevicesExplicitly = 0;
pVBoxAPI->vboxAttachDrivesUseOld = 0;
+ pVBoxAPI->supportScreenshot = 1;
#else /* VBOX_API_VERSION < 4000000 */
pVBoxAPI->getMachineForSession = 0;
pVBoxAPI->detachDevicesExplicitly = 1;
pVBoxAPI->vboxAttachDrivesUseOld = 1;
+ pVBoxAPI->supportScreenshot = 0;
#endif /* VBOX_API_VERSION < 4000000 */
#if VBOX_API_VERSION >= 4001000
diff --git a/src/vbox/vbox_uniformed_api.h b/src/vbox/vbox_uniformed_api.h
index 2800b60..7e8f677 100644
--- a/src/vbox/vbox_uniformed_api.h
+++ b/src/vbox/vbox_uniformed_api.h
@@ -273,6 +273,7 @@ typedef struct {
nsresult (*TakeSnapshot)(IConsole *console, PRUnichar *name,
PRUnichar *description, IProgress **progress);
nsresult (*DeleteSnapshot)(IConsole *console, vboxIIDUnion *iidu, IProgress
**progress);
+ nsresult (*GetDisplay)(IConsole *console, IDisplay **display);
} vboxUniformedIConsole;
/* Functions for IProgress */
@@ -446,6 +447,23 @@ typedef struct {
nsresult (*GetOnline)(ISnapshot *snapshot, PRBool *online);
} vboxUniformedISnapshot;
+/* Functions for IDisplay */
+typedef struct {
+ nsresult (*GetScreenResolution)(IDisplay *display,
+ PRUint32 screenId,
+ PRUint32 *width,
+ PRUint32 *height,
+ PRUint32 *bitsPerPixel,
+ PRInt32 *xOrigin,
+ PRInt32 *yOrigin);
+ nsresult (*TakeScreenShotPNGToArray)(IDisplay *display,
+ PRUint32 screenId,
+ PRUint32 width,
+ PRUint32 height,
+ PRUint32 *screenDataSize,
+ PRUint8** screenData);
+} vboxUniformedIDisplay;
+
typedef struct {
bool (*Online)(PRUint32 state);
bool (*Inactive)(PRUint32 state);
@@ -498,6 +516,7 @@ typedef struct {
vboxUniformedIStorageController UIStorageController;
vboxUniformedISharedFolder UISharedFolder;
vboxUniformedISnapshot UISnapshot;
+ vboxUniformedIDisplay UIDisplay;
uniformedMachineStateChecker machineStateChecker;
/* vbox API features */
bool domainEventCallbacks;
@@ -509,6 +528,7 @@ typedef struct {
bool vboxAttachDrivesUseOld;
bool oldMediumInterface;
bool vboxSnapshotRedefine;
+ bool supportScreenshot;
} vboxUniformedAPI;
/* libvirt API
@@ -599,7 +619,8 @@ int vboxDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
unsigned int flags);
int vboxDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
unsigned int flags);
-
+char *vboxDomainScreenshot(virDomainPtr dom, virStreamPtr st,
+ unsigned int screen, unsigned int flags);
/* Version specified functions for installing uniformed API */
void vbox22InstallUniformedAPI(vboxUniformedAPI *pVBoxAPI);
--
1.7.9.5