Index: /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h	(revision 52562)
@@ -24,31 +24,30 @@
 
 /** Exit with a fatal error. */
-#define FatalError(format) \
+#define VBClFatalError(format) \
 do { \
     char *pszMessage = RTStrAPrintf2 format; \
     LogRel(format); \
-    doFatalError(pszMessage); \
+    vbclFatalError(pszMessage); \
 } while(0)
 
 /** Exit with a fatal error. */
-extern void doFatalError(char *pszMessage);
+extern void vbclFatalError(char *pszMessage);
 
-/** Namespace for VBoxClient-specific things */
-namespace VBoxClient {
+/** Call clean-up for the current service and exit. */
+extern void VBClCleanUp();
 
-/** A simple class describing a service.  VBoxClient will run exactly one
+/** A simple interface describing a service.  VBoxClient will run exactly one
  * service per invocation. */
-class Service : public RTCNonCopyable
+struct VBCLSERVICE
 {
-public:
     /** Get the services default path to pidfile, relative to $HOME */
     /** @todo Should this also have a component relative to the X server number?
      */
-    virtual const char *getPidFilePath() = 0;
+    const char *(*getPidFilePath)(void);
     /** Special initialisation, if needed.  @a pause and @a resume are
      * guaranteed not to be called until after this returns. */
-    virtual int init() { return VINF_SUCCESS; }
+    int (*init)(struct VBCLSERVICE **ppInterface);
     /** Run the service main loop */
-    virtual int run(bool fDaemonised = false) = 0;
+    int (*run)(struct VBCLSERVICE **ppInterface, bool fDaemonised);
     /** Pause the service loop.  This must be safe to call on a different thread
      * and potentially before @a run is or after it exits.
@@ -57,26 +56,34 @@
      * is available then @a pause or @a resume will be called as soon as it starts
      * up. */
-    virtual int pause() { return VINF_SUCCESS; }
+    int (*pause)(struct VBCLSERVICE **ppInterface);
     /** Resume after pausing.  The same applies here as for @a pause. */
-    virtual int resume() { return VINF_SUCCESS; }
+    int (*resume)(struct VBCLSERVICE **ppInterface);
     /** Clean up any global resources before we shut down hard.  The last calls
      * to @a pause and @a resume are guaranteed to finish before this is called.
      */
-    virtual void cleanup() = 0;
-    /** Virtual destructor.  Not used */
-    virtual ~Service() {}
+    void (*cleanup)(struct VBCLSERVICE **ppInterface);
 };
 
-extern Service *GetClipboardService();
-extern Service *GetSeamlessService();
-extern Service *GetDisplayService();
-extern Service *GetHostVersionService();
+/** Default handler for various struct VBCLSERVICE member functions. */
+static int VBClServiceDefaultHandler(struct VBCLSERVICE **pSelf)
+{
+    return VINF_SUCCESS;
+}
+
+/** Default handler for the struct VBCLSERVICE clean-up member function.
+ * Usually used because the service is cleaned up automatically when the user
+ * process/X11 exits. */
+static void VBClServiceDefaultCleanup(struct VBCLSERVICE **ppInterface)
+{
+    NOREF(ppInterface);
+}
+
+extern struct VBCLSERVICE **VBClGetClipboardService();
+extern struct VBCLSERVICE **VBClGetSeamlessService();
+extern struct VBCLSERVICE **VBClGetDisplayService();
+extern struct VBCLSERVICE **VBClGetHostVersionService();
 #ifdef VBOX_WITH_DRAG_AND_DROP
-extern Service *GetDragAndDropService();
+extern struct VBCLSERVICE **VBClGetDragAndDropService();
 #endif /* VBOX_WITH_DRAG_AND_DROP */
 
-extern void CleanUp();
-
-} /* namespace VBoxClient */
-
 #endif /* !___vboxclient_vboxclient_h */
Index: /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp	(revision 52562)
@@ -278,28 +278,44 @@
 }
 
-class ClipboardService : public VBoxClient::Service
-{
-public:
-    virtual const char *getPidFilePath()
-    {
-        return ".vboxclient-clipboard.pid";
-    }
-    virtual int run(bool fDaemonised /* = false */)
-    {
-        int rc = vboxClipboardConnect();
-        if (RT_SUCCESS(rc))
-            rc = vboxClipboardMain();
-        if (RT_FAILURE(rc))
-            LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc));
-        return rc;
-    }
-    virtual void cleanup()
-    {
-        /* Nothing to do. */
-    }
+static const char *getPidFilePath()
+{
+    return ".vboxclient-clipboard.pid";
+}
+
+static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+{
+    int rc = vboxClipboardConnect();
+
+    NOREF(ppInterface);
+    if (RT_SUCCESS(rc))
+        rc = vboxClipboardMain();
+    if (RT_FAILURE(rc))
+        LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc));
+    return rc;
+}
+
+struct VBCLSERVICE vbclClipboardInterface =
+{
+    getPidFilePath,
+    VBClServiceDefaultHandler, /* init */
+    run,
+    VBClServiceDefaultHandler, /* pause */
+    VBClServiceDefaultHandler, /* resume */
+    VBClServiceDefaultCleanup    
 };
 
-VBoxClient::Service *VBoxClient::GetClipboardService()
-{
-    return new ClipboardService;
-}
+struct CLIPBOARDSERVICE
+{
+    struct VBCLSERVICE *pInterface;
+};
+
+struct VBCLSERVICE **VBClGetClipboardService()
+{
+    struct CLIPBOARDSERVICE *pService =
+        (struct CLIPBOARDSERVICE *)RTMemAlloc(sizeof(*pService));
+
+    if (!pService)
+        VBClFatalError(("Out of memory\n"));
+    pService->pInterface = &vbclClipboardInterface;
+    return &pService->pInterface;
+}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/display.cpp	(revision 52562)
@@ -64,12 +64,12 @@
     int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));
     rc = VbglR3SetMouseStatus(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
     rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
                                 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
     return VINF_SUCCESS;
 }
@@ -82,11 +82,11 @@
                                  | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));
     rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));
     rc = VbglR3SetMouseStatus(0);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));
+        VBClFatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));
     return VINF_SUCCESS;
 }
@@ -106,5 +106,5 @@
     status = system(pState->pcszXrandr);
     if (WEXITSTATUS(status) != 0)  /* Utility or extension not available. */
-        FatalError(("Failed to execute the xrandr utility.\n"));
+        VBClFatalError(("Failed to execute the xrandr utility.\n"));
     RTStrPrintf(szCommand, sizeof(szCommand), "%s --q12", pState->pcszXrandr);
     status = system(szCommand);
@@ -130,5 +130,5 @@
                                                 * sizeof(*pState->paSizeHints));
         if (!pState->paSizeHints)
-            FatalError(("Failed to re-allocate size hint memory.\n"));
+            VBClFatalError(("Failed to re-allocate size hint memory.\n"));
         for (i = pState->cSizeHints; i < iDisplay + 1; ++i)
             pState->paSizeHints[i] = 0;
@@ -151,5 +151,5 @@
         status = system(szCommand);
         if (WEXITSTATUS(status) != 0)
-            FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
+            VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     }
     else
@@ -164,5 +164,5 @@
             status = system(szCommand);
             if (WEXITSTATUS(status) != 0)
-                FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
+                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
         }
         if ((!fSetPosition || fEnabled) && cx != 0 && cy != 0)
@@ -173,5 +173,5 @@
             status = system(szCommand);
             if (WEXITSTATUS(status) != 0)
-                FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
+                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
         }
         if (!fEnabled)
@@ -183,5 +183,5 @@
             status = system(szCommand);
             if (WEXITSTATUS(status) != 0)
-                FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
+                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
         }
     }
@@ -206,5 +206,5 @@
     rc = VbglR3VideoModeGetHighestSavedScreen(&cScreens);
     if (RT_FAILURE(rc))
-        FatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n",
+        VBClFatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n",
                     rc));
     for (i = 0; i < RT_MAX(cScreens + 1, 8); ++i)
@@ -216,5 +216,5 @@
                                      &fEnabled);
         if (RT_SUCCESS(rc) && i > cScreens) /* Sanity */
-            FatalError(("Internal error retrieving the number of saved screen modes.\n"));
+            VBClFatalError(("Internal error retrieving the number of saved screen modes.\n"));
         if (RT_SUCCESS(rc))
             setModeX11(pState, cx, cy, cBPP, i, x, y, fEnabled,
@@ -230,5 +230,5 @@
         while(rc == VERR_INTERRUPTED);
         if (RT_FAILURE(rc))  /* VERR_NO_MEMORY? */
-            FatalError(("event wait failed, rc=%Rrc\n", rc));
+            VBClFatalError(("event wait failed, rc=%Rrc\n", rc));
         if (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
         {
@@ -262,5 +262,5 @@
             {
                 if (rc != VERR_NOT_IMPLEMENTED)
-                    FatalError(("Failed to get display change request, rc=%Rrc\n",
+                    VBClFatalError(("Failed to get display change request, rc=%Rrc\n",
                                 rc));
                 fSetPosition = false;
@@ -276,11 +276,11 @@
                                 fEnabled));
             if (RT_FAILURE(rc))
-                FatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));
+                VBClFatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));
             if (iDisplay > INT32_MAX)
-                FatalError(("Received a size hint for too high display number %u\n",
+                VBClFatalError(("Received a size hint for too high display number %u\n",
                             (unsigned) iDisplay));
             rc = VbglR3SeamlessGetLastEvent(&Mode);
             if (RT_FAILURE(rc))
-                FatalError(("Failed to check seamless mode, rc=%Rrc\n", rc));
+                VBClFatalError(("Failed to check seamless mode, rc=%Rrc\n", rc));
             if (Mode == VMMDev_Seamless_Disabled)
             {
@@ -290,5 +290,5 @@
                     && rc != VERR_HGCM_SERVICE_NOT_FOUND
                     && rc != VERR_NOT_IMPLEMENTED /* No HGCM */)
-                    FatalError(("Failed to save size hint, rc=%Rrc\n", rc));
+                    VBClFatalError(("Failed to save size hint, rc=%Rrc\n", rc));
             }
             setModeX11(pState, cx, cy, cBPP, iDisplay, x, y, fEnabled,
@@ -298,55 +298,106 @@
 }
 
-class DisplayService : public VBoxClient::Service
-{
+/** Display magic number, start of a UUID. */
+#define DISPLAYSERVICE_MAGIC 0xf0029993
+
+/** VBoxClient service class wrapping the logic for the display service while
+ *  the main VBoxClient code provides the daemon logic needed by all services.
+ */
+struct DISPLAYSERVICE
+{
+    /** The service interface. */
+    struct VBCLSERVICE *pInterface;
+    /** Magic number for sanity checks. */
+    uint32_t magic;
+    /** State related to the X server. */
     struct x11State mState;
+    /** Are we initialised yet? */
     bool mfInit;
-public:
-    virtual const char *getPidFilePath()
-    {
-        return ".vboxclient-display.pid";
-    }
-    virtual int init()
-    {
-        int rc;
-        
-        if (mfInit)
-            return VERR_WRONG_ORDER;
-        rc = initX11(&mState);
-        if (RT_FAILURE(rc))
-            return rc;
-        rc = enableEventsAndCaps();
-        if (RT_SUCCESS(rc))
-            mfInit = true;
+};
+
+static const char *getPidFilePath()
+{
+    return ".vboxclient-display.pid";
+}
+
+static struct DISPLAYSERVICE *getClassFromInterface(struct VBCLSERVICE **
+                                                         ppInterface)
+{
+    struct DISPLAYSERVICE *pSelf = (struct DISPLAYSERVICE *)ppInterface;
+    if (pSelf->magic != DISPLAYSERVICE_MAGIC)
+        VBClFatalError(("Bad display service object!\n"));
+    return pSelf;
+}
+
+static int init(struct VBCLSERVICE **ppInterface)
+{
+    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
+    int rc;
+    
+    if (pSelf->mfInit)
+        return VERR_WRONG_ORDER;
+    rc = initX11(&pSelf->mState);
+    if (RT_FAILURE(rc))
         return rc;
-    }
-    virtual int run(bool fDaemonised /* = false */)
-    {
-        if (!mfInit)
-            return VERR_WRONG_ORDER;
-        runDisplay(&mState);
-        return VERR_INTERNAL_ERROR;  /* "Should never reach here." */
-    }
-    virtual int pause()
-    {
-        if (!mfInit)
-            return VERR_WRONG_ORDER;
-        return disableEventsAndCaps();
-    }
-    virtual int resume()
-    {
-        if (!mfInit)
-            return VERR_WRONG_ORDER;
-        return enableEventsAndCaps();
-    }
-    virtual void cleanup()
-    {
-        disableEventsAndCaps();
-    }
-    DisplayService() { mfInit = false; }
+    rc = enableEventsAndCaps();
+    if (RT_SUCCESS(rc))
+        pSelf->mfInit = true;
+    return rc;
+}
+
+static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+{
+    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
+
+    if (!pSelf->mfInit)
+        return VERR_WRONG_ORDER;
+    runDisplay(&pSelf->mState);
+    return VERR_INTERNAL_ERROR;  /* "Should never reach here." */
+}
+
+static int pause(struct VBCLSERVICE **ppInterface)
+{
+    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
+
+    if (!pSelf->mfInit)
+        return VERR_WRONG_ORDER;
+    return disableEventsAndCaps();
+}
+
+static int resume(struct VBCLSERVICE **ppInterface)
+{
+    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
+
+    if (!pSelf->mfInit)
+        return VERR_WRONG_ORDER;
+    return enableEventsAndCaps();
+}
+
+static void cleanup(struct VBCLSERVICE **ppInterface)
+{
+    NOREF(ppInterface);
+    disableEventsAndCaps();
+}
+
+struct VBCLSERVICE vbclDisplayInterface =
+{
+    getPidFilePath,
+    init,
+    run,
+    pause,
+    resume,
+    cleanup    
 };
 
-VBoxClient::Service *VBoxClient::GetDisplayService()
-{
-    return new DisplayService;
-}
+struct VBCLSERVICE **VBClGetDisplayService()
+{
+    struct DISPLAYSERVICE *pService =
+        (struct DISPLAYSERVICE *)RTMemAlloc(sizeof(*pService));
+
+    if (!pService)
+        VBClFatalError(("Out of memory\n"));
+    pService->pInterface = &vbclDisplayInterface;
+    pService->magic = DISPLAYSERVICE_MAGIC;
+    pService->mfInit = false;
+    return &pService->pInterface;
+}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 52562)
@@ -441,5 +441,5 @@
  ******************************************************************************/
 
-class DragAndDropService : public VBoxClient::Service
+class DragAndDropService
 {
 public:
@@ -453,13 +453,5 @@
     {}
 
-    virtual const char *getPidFilePath() { return ".vboxclient-draganddrop.pid"; }
-
-    virtual int run(bool fDaemonised = false);
-
-    virtual void cleanup(void)
-    {
-        /* Nothing to do, everything should be cleaned up automatically when the
-         * user process/X11 client exits. */
-    };
+    int run(bool fDaemonised = false);
 
 private:
@@ -2387,9 +2379,56 @@
 }
 
+/** Drag and drop magic number, start of a UUID. */
+#define DRAGANDDROPSERVICE_MAGIC 0x67c97173
+
+/** VBoxClient service class wrapping the logic for the service while
+ *  the main VBoxClient code provides the daemon logic needed by all services.
+ */
+struct DRAGANDDROPSERVICE
+{
+    /** The service interface. */
+    struct VBCLSERVICE *pInterface;
+    /** Magic number for sanity checks. */
+    uint32_t magic;
+    /** Service object. */
+    DragAndDropService mDragAndDrop;
+};
+
+static const char *getPidFilePath()
+{
+    return ".vboxclient-draganddrop.pid";
+}
+
+static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+{
+    struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
+
+    if (pSelf->magic != DRAGANDDROPSERVICE_MAGIC)
+        VBClFatalError(("Bad display service object!\n"));
+    return pSelf->mDragAndDrop.run(fDaemonised);
+}
+
+struct VBCLSERVICE vbclDragAndDropInterface =
+{
+    getPidFilePath,
+    VBClServiceDefaultHandler, /* init */
+    run,
+    VBClServiceDefaultHandler, /* pause */
+    VBClServiceDefaultHandler, /* resume */
+    VBClServiceDefaultCleanup    
+};
+
 /* Static factory */
-VBoxClient::Service *VBoxClient::GetDragAndDropService(void)
-{
-    DragAndDropService *pService = new DragAndDropService();
-    return pService;
-}
-
+struct VBCLSERVICE **VBClGetDragAndDropService(void)
+{
+    struct DRAGANDDROPSERVICE *pService =
+        (struct DRAGANDDROPSERVICE *)RTMemAlloc(sizeof(*pService));
+
+    if (!pService)
+        VBClFatalError(("Out of memory\n"));
+    pService->pInterface = &vbclDragAndDropInterface;
+    pService->magic = DRAGANDDROPSERVICE_MAGIC;
+    new(&pService->mDragAndDrop) DragAndDropService();
+    return &pService->pInterface;
+}
+
Index: /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp	(revision 52562)
@@ -17,4 +17,5 @@
 #include <iprt/assert.h>
 #include <iprt/err.h>
+#include <iprt/mem.h>
 #include <iprt/ldr.h>
 #include <iprt/string.h>
@@ -32,182 +33,193 @@
 #include "VBoxClient.h"
 
-class HostVersionService : public VBoxClient::Service
-{
-
-public:
-
-    virtual const char *getPidFilePath()
-    {
-        return ".vboxclient-hostversion.pid";
-    }
-
-    virtual int showNotify(const char *pcHeader, const char *pcBody)
-    {
-        int rc;
+static const char *getPidFilePath()
+{
+    return ".vboxclient-hostversion.pid";
+}
+
+static int showNotify(const char *pcHeader, const char *pcBody)
+{
+    int rc;
 # ifdef VBOX_WITH_DBUS
-        DBusConnection *conn;
-        DBusMessage* msg = NULL;
-        conn = dbus_bus_get (DBUS_BUS_SESSON, NULL);
-        if (conn == NULL)
-        {
-            LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
+    DBusConnection *conn;
+    DBusMessage* msg = NULL;
+    conn = dbus_bus_get (DBUS_BUS_SESSON, NULL);
+    if (conn == NULL)
+    {
+        LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
+        rc = VERR_INVALID_HANDLE;
+    }
+    else
+    {
+        msg = dbus_message_new_method_call("org.freedesktop.Notifications",
+                                           "/org/freedesktop/Notifications",
+                                           "org.freedesktop.Notifications",
+                                           "Notify");
+        if (msg == NULL)
+        {
+            LogRel(("Could not create D-BUS message!\n"));
             rc = VERR_INVALID_HANDLE;
         }
         else
-        {
-            msg = dbus_message_new_method_call("org.freedesktop.Notifications",
-                                               "/org/freedesktop/Notifications",
-                                               "org.freedesktop.Notifications",
-                                               "Notify");
-            if (msg == NULL)
+            rc = VINF_SUCCESS;
+    }
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t msg_replace_id = 0;
+        const char *msg_app = "VBoxClient";
+        const char *msg_icon = "";
+        const char *msg_summary = pcHeader;
+        const char *msg_body = pcBody;
+        int32_t msg_timeout = -1;           /* Let the notification server decide */
+
+        DBusMessageIter iter;
+        DBusMessageIter array;
+        DBusMessageIter dict;
+        DBusMessageIter value;
+        DBusMessageIter variant;
+        DBusMessageIter data;
+
+        /* Format: UINT32 org.freedesktop.Notifications.Notify
+         *         (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body,
+         *          ARRAY actions, DICT hints, INT32 expire_timeout)
+         */
+        dbus_message_iter_init_append(msg,&iter);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body);
+        dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
+        dbus_message_iter_close_container(&iter,&array);
+        dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array);
+        dbus_message_iter_close_container(&iter,&array);
+        dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout);
+
+        DBusError err;
+        dbus_error_init(&err);
+
+        DBusMessage *reply;
+        reply = dbus_connection_send_with_reply_and_block(conn, msg,
+            30 * 1000 /* 30 seconds timeout */, &err);
+        if (dbus_error_is_set(&err))
+        {
+            LogRel(("D-BUS returned an error while sending the notification: %s", err.message));
+        }
+        else if (reply)
+        {
+            dbus_connection_flush(conn);
+            dbus_message_unref(reply);
+        }
+        if (dbus_error_is_set(&err))
+            dbus_error_free(&err);
+    }
+    if (msg != NULL)
+        dbus_message_unref(msg);
+# else
+    /* TODO: Implement me */
+    rc = VINF_SUCCESS;
+# endif /* VBOX_WITH_DBUS */
+    return rc;
+}
+
+/** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
+          notification stuff, since this is very similar to the VBoxTray code. */
+static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+{
+    int rc;
+    LogFlowFunc(("\n"));
+
+    NOREF(ppInterface);
+    /* Because we need desktop notifications to be displayed, wait
+     * some time to make the desktop environment load (as a work around). */
+    if (fDaemonised)
+        RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
+
+# ifdef VBOX_WITH_DBUS
+    rc = RTDBusLoadLib();
+    if (RT_FAILURE(rc))
+        LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
+# else
+    rc = VERR_NOT_IMPLEMENTED;
+# endif /* VBOX_WITH_DBUS */
+
+# ifdef VBOX_WITH_GUEST_PROPS
+    uint32_t uGuestPropSvcClientID;
+    if (RT_SUCCESS(rc))
+    {
+        rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
+        if (RT_FAILURE(rc))
+            LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        char *pszHostVersion;
+        char *pszGuestVersion;
+        bool bUpdate;
+
+        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
+        if (RT_SUCCESS(rc))
+        {
+            if (bUpdate)
             {
-                LogRel(("Could not create D-BUS message!\n"));
-                rc = VERR_INVALID_HANDLE;
-            }
-            else
-                rc = VINF_SUCCESS;
-        }
-        if (RT_SUCCESS(rc))
-        {
-            uint32_t msg_replace_id = 0;
-            const char *msg_app = "VBoxClient";
-            const char *msg_icon = "";
-            const char *msg_summary = pcHeader;
-            const char *msg_body = pcBody;
-            int32_t msg_timeout = -1;           /* Let the notification server decide */
-
-            DBusMessageIter iter;
-            DBusMessageIter array;
-            DBusMessageIter dict;
-            DBusMessageIter value;
-            DBusMessageIter variant;
-            DBusMessageIter data;
-
-            /* Format: UINT32 org.freedesktop.Notifications.Notify
-             *         (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body,
-             *          ARRAY actions, DICT hints, INT32 expire_timeout)
-             */
-            dbus_message_iter_init_append(msg,&iter);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body);
-            dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
-            dbus_message_iter_close_container(&iter,&array);
-            dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array);
-            dbus_message_iter_close_container(&iter,&array);
-            dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout);
-
-            DBusError err;
-            dbus_error_init(&err);
-
-            DBusMessage *reply;
-            reply = dbus_connection_send_with_reply_and_block(conn, msg,
-                30 * 1000 /* 30 seconds timeout */, &err);
-            if (dbus_error_is_set(&err))
-            {
-                LogRel(("D-BUS returned an error while sending the notification: %s", err.message));
-            }
-            else if (reply)
-            {
-                dbus_connection_flush(conn);
-                dbus_message_unref(reply);
-            }
-            if (dbus_error_is_set(&err))
-                dbus_error_free(&err);
-        }
-        if (msg != NULL)
-            dbus_message_unref(msg);
-# else
-        /* TODO: Implement me */
-        rc = VINF_SUCCESS;
-# endif /* VBOX_WITH_DBUS */
-        return rc;
-    }
-
-    /** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
-              notification stuff, since this is very similar to the VBoxTray code. */
-    virtual int run(bool fDaemonised /* = false */)
-    {
-        int rc;
-        LogFlowFunc(("\n"));
-
-        /* Because we need desktop notifications to be displayed, wait
-         * some time to make the desktop environment load (as a work around). */
-        if (fDaemonised)
-            RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
-
-# ifdef VBOX_WITH_DBUS
-        rc = RTDBusLoadLib();
-        if (RT_FAILURE(rc))
-            LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
-# else
-        rc = VERR_NOT_IMPLEMENTED;
-# endif /* VBOX_WITH_DBUS */
-
-# ifdef VBOX_WITH_GUEST_PROPS
-        uint32_t uGuestPropSvcClientID;
-        if (RT_SUCCESS(rc))
-        {
-            rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
-            if (RT_FAILURE(rc))
-                LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
-        }
-
-        if (RT_SUCCESS(rc))
-        {
-            char *pszHostVersion;
-            char *pszGuestVersion;
-            bool bUpdate;
-
-            rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
-            if (RT_SUCCESS(rc))
-            {
-                if (bUpdate)
-                {
-                    char szMsg[1024];
-                    char szTitle[64];
-
-                    /** @todo add some translation macros here */
-                    RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
+                char szMsg[1024];
+                char szTitle[64];
+
+                /** @todo add some translation macros here */
+                RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
 #ifndef VBOX_OSE
-                    RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
-                                                      "We recommend updating to the latest version (%s) by choosing the "
-                                                      "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
+                RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
+                                                  "We recommend updating to the latest version (%s) by choosing the "
+                                                  "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
 #else
 /* This is the message which appears for non-Oracle builds of the
- * Guest Additions.  Distributors are encouraged to customise this. */
-                    RTStrPrintf(szMsg, sizeof(szMsg), "Your virtual machine is currently running the Guest Additions version %s. Since you are running a version of the Guest Additions provided by the operating system you installed in the virtual machine we recommend that you update it to at least version %s using that system's update features, or alternatively that you remove this version and then install the " VBOX_VENDOR_SHORT " Guest Additions package using the install option from the Devices menu. Please consult the documentation for the operating system you are running to find out how to update or remove the current Guest Additions package.", pszGuestVersion, pszHostVersion);
+* Guest Additions.  Distributors are encouraged to customise this. */
+                RTStrPrintf(szMsg, sizeof(szMsg), "Your virtual machine is currently running the Guest Additions version %s. Since you are running a version of the Guest Additions provided by the operating system you installed in the virtual machine we recommend that you update it to at least version %s using that system's update features, or alternatively that you remove this version and then install the " VBOX_VENDOR_SHORT " Guest Additions package using the install option from the Devices menu. Please consult the documentation for the operating system you are running to find out how to update or remove the current Guest Additions package.", pszGuestVersion, pszHostVersion);
 #endif
-                    rc = showNotify(szTitle, szMsg);
-                    LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
-                    if (RT_FAILURE(rc))
-                        LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
-                }
-
-                /* Store host version to not notify again */
-                rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);
-
-                VbglR3GuestPropReadValueFree(pszHostVersion);
-                VbglR3GuestPropReadValueFree(pszGuestVersion);
+                rc = showNotify(szTitle, szMsg);
+                LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
+                if (RT_FAILURE(rc))
+                    LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
             }
-            VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
-        }
+
+            /* Store host version to not notify again */
+            rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);
+
+            VbglR3GuestPropReadValueFree(pszHostVersion);
+            VbglR3GuestPropReadValueFree(pszGuestVersion);
+        }
+        VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
+    }
 # endif /* VBOX_WITH_GUEST_PROPS */
-        LogFlowFunc(("returning %Rrc\n", rc));
-        return rc;
-    }
-
-    virtual void cleanup()
-    {
-
-    }
+    LogFlowFunc(("returning %Rrc\n", rc));
+    return rc;
+}
+
+struct VBCLSERVICE vbclHostVersionInterface =
+{
+    getPidFilePath,
+    VBClServiceDefaultHandler, /* init */
+    run,
+    VBClServiceDefaultHandler, /* pause */
+    VBClServiceDefaultHandler, /* resume */
+    VBClServiceDefaultCleanup    
 };
 
+struct HOSTVERSIONSERVICE
+{
+    struct VBCLSERVICE *pInterface;
+};
+
 /* Static factory */
-VBoxClient::Service *VBoxClient::GetHostVersionService()
-{
-    return new HostVersionService;
-}
-
+struct VBCLSERVICE **VBClGetHostVersionService()
+{
+    struct HOSTVERSIONSERVICE *pService =
+        (struct HOSTVERSIONSERVICE *)RTMemAlloc(sizeof(*pService));
+
+    if (!pService)
+        VBClFatalError(("Out of memory\n"));
+    pService->pInterface = &vbclHostVersionInterface;
+    return &pService->pInterface;
+}
+
Index: /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/main.cpp	(revision 52562)
@@ -48,5 +48,5 @@
 /** Object representing the service we are running.  This has to be global
  * so that the cleanup routine can access it. */
-VBoxClient::Service *g_pService;
+struct VBCLSERVICE **g_pService;
 /** The name of our pidfile.  It is global for the benefit of the cleanup
  * routine. */
@@ -62,5 +62,5 @@
 
 /** Exit with a fatal error. */
-void doFatalError(char *pszMessage)
+void vbclFatalError(char *pszMessage)
 {
     char *pszCommand;
@@ -77,5 +77,5 @@
 /** Clean up if we get a signal or something.  This is extern so that we
  * can call it from other compilation units. */
-void VBoxClient::CleanUp()
+void VBClCleanUp()
 {
     /* We never release this, as we end up with a call to exit(3) which is not
@@ -89,5 +89,5 @@
     }
     if (g_pService)
-        g_pService->cleanup();
+        (*g_pService)->cleanup(g_pService);
     if (g_szPidFile[0] && g_hPidFile)
         VbglR3ClosePidFile(g_szPidFile, g_hPidFile);
@@ -104,5 +104,5 @@
     /** Disable seamless mode */
     RTPrintf(("VBoxClient: terminating...\n"));
-    VBoxClient::CleanUp();
+    VBClCleanUp();
 }
 
@@ -126,5 +126,5 @@
 {
     LogRel(("VBoxClient: a fatal guest X Window error occurred.  This may just mean that the Window system was shut down while the client was still running.\n"));
-    VBoxClient::CleanUp();
+    VBClCleanUp();
     return 0;  /* We should never reach this. */
 }
@@ -200,7 +200,7 @@
         pcszStage = "asking service to pause or resume";
         if (cTTY == cVT)
-            rc = g_pService->resume();
+            rc = (*g_pService)->resume(g_pService);
         else
-            rc = g_pService->pause();
+            rc = (*g_pService)->pause(g_pService);
         if (RT_FAILURE(rc))
             break;
@@ -214,5 +214,5 @@
         if (RTCritSectIsOwner(&g_critSect))
             RTCritSectLeave(&g_critSect);
-        VBoxClient::CleanUp();
+        VBClCleanUp();
     }
 }
@@ -273,5 +273,5 @@
         {
             LogRel(("Monitor thread: poll failed, stopping.\n"));
-            VBoxClient::CleanUp();
+            VBClCleanUp();
         }
     }
@@ -397,5 +397,5 @@
             if (g_pService)
                 break;
-            g_pService = VBoxClient::GetClipboardService();
+            g_pService = VBClGetClipboardService();
         }
         else if (!strcmp(argv[i], "--display"))
@@ -403,5 +403,5 @@
             if (g_pService)
                 break;
-            g_pService = VBoxClient::GetDisplayService();
+            g_pService = VBClGetDisplayService();
         }
         else if (!strcmp(argv[i], "--seamless"))
@@ -409,5 +409,5 @@
             if (g_pService)
                 break;
-            g_pService = VBoxClient::GetSeamlessService();
+            g_pService = VBClGetSeamlessService();
         }
         else if (!strcmp(argv[i], "--checkhostversion"))
@@ -415,5 +415,5 @@
             if (g_pService)
                 break;
-            g_pService = VBoxClient::GetHostVersionService();
+            g_pService = VBClGetHostVersionService();
         }
 #ifdef VBOX_WITH_DRAG_AND_DROP
@@ -422,5 +422,5 @@
             if (g_pService)
                 break;
-            g_pService = VBoxClient::GetDragAndDropService();
+            g_pService = VBClGetDragAndDropService();
         }
 #endif /* VBOX_WITH_DRAG_AND_DROP */
@@ -455,5 +455,5 @@
         pcszStage = "Creating pid-file path";
         rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile),
-                          g_pService->getPidFilePath());
+                          (*g_pService)->getPidFilePath());
         if (RT_FAILURE(rc))
             break;
@@ -477,5 +477,5 @@
         XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
         pcszStage = "Initialising service";
-        rc = g_pService->init();
+        rc = (*g_pService)->init(g_pService);
     } while (0);
     if (RT_FAILURE(rc))
@@ -492,6 +492,6 @@
                  rc));
     else
-        g_pService->run(fDaemonise);  /* Should never return. */
-    VBoxClient::CleanUp();
+        (*g_pService)->run(g_pService, fDaemonise);  /* Should never return. */
+    VBClCleanUp();
     return 1;
 }
Index: /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp	(revision 52562)
@@ -27,7 +27,10 @@
 #include <VBox/VBoxGuestLib.h>
 #include <iprt/err.h>
+#include <iprt/mem.h>
 
 #include "VBoxClient.h"
 #include "seamless.h"
+
+#include <new>
 
 SeamlessMain::SeamlessMain(void)
@@ -316,55 +319,110 @@
 }
 
+/** Service magic number, start of a UUID. */
+#define SEAMLESSSERVICE_MAGIC 0xd28ba727
+
 /** VBoxClient service class wrapping the logic for the seamless service while
  *  the main VBoxClient code provides the daemon logic needed by all services.
  */
-class SeamlessService : public VBoxClient::Service
-{
-private:
+struct SEAMLESSSERVICE
+{
+    /** The service interface. */
+    struct VBCLSERVICE *pInterface;
+    /** Magic number for sanity checks. */
+    uint32_t magic;
+    /** Seamless service object. */
     SeamlessMain mSeamless;
+    /** Are we initialised yet? */
     bool mIsInitialised;
-public:
-    virtual const char *getPidFilePath()
-    {
-        return ".vboxclient-seamless.pid";
-    }
-    virtual int init()
-    {
-        int rc;
-
-        if (mIsInitialised)
-            return VERR_INTERNAL_ERROR;
-        rc = mSeamless.init();
-        if (RT_FAILURE(rc))
-            return rc;
-        rc = mSeamless.selfTest();
-        if (RT_FAILURE(rc))
-        {
-            mSeamless.stop();
-            return rc;
-        }
-        mIsInitialised = true;
-        return VINF_SUCCESS;
-    }
-    virtual int run(bool fDaemonised /* = false */)
-    {
-        int rc;
-        if (!mIsInitialised)
-            return VERR_INTERNAL_ERROR;
-        /* This only exits on error. */
-        rc = mSeamless.run();
-        mIsInitialised = false;
+};
+
+static const char *getPidFilePath(void)
+{
+    return ".vboxclient-seamless.pid";
+}
+
+static struct SEAMLESSSERVICE *getClassFromInterface(struct VBCLSERVICE **
+                                                         ppInterface)
+{
+    struct SEAMLESSSERVICE *pSelf = (struct SEAMLESSSERVICE *)ppInterface;
+    if (pSelf->magic != SEAMLESSSERVICE_MAGIC)
+        VBClFatalError(("Bad seamless service object!\n"));
+    return pSelf;
+}
+
+static int init(struct VBCLSERVICE **ppInterface)
+{
+    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
+    int rc;
+
+    if (pSelf->mIsInitialised)
+        return VERR_INTERNAL_ERROR;
+    rc = pSelf->mSeamless.init();
+    if (RT_FAILURE(rc))
         return rc;
-    }
-    virtual int pause() { return mSeamless.pause(); }
-    virtual int resume() { return mSeamless.resume(); }
-    virtual void cleanup()
-    {
-        VbglR3SeamlessSetCap(false);
-    }
+    rc = pSelf->mSeamless.selfTest();
+    if (RT_FAILURE(rc))
+    {
+        pSelf->mSeamless.stop();
+        return rc;
+    }
+    pSelf->mIsInitialised = true;
+    return VINF_SUCCESS;
+}
+
+static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
+{
+    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
+    int rc;
+
+    if (!pSelf->mIsInitialised)
+        return VERR_INTERNAL_ERROR;
+    /* This only exits on error. */
+    rc = pSelf->mSeamless.run();
+    pSelf->mIsInitialised = false;
+    return rc;
+}
+
+static int pause(struct VBCLSERVICE **ppInterface)
+{
+    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
+
+    return pSelf->mSeamless.pause();
+}
+
+static int resume(struct VBCLSERVICE **ppInterface)
+{
+    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
+
+    return pSelf->mSeamless.resume();
+}
+
+static void cleanup(struct VBCLSERVICE **ppInterface)
+{
+    NOREF(ppInterface);
+    VbglR3SeamlessSetCap(false);
+}
+
+struct VBCLSERVICE vbclSeamlessInterface =
+{
+    getPidFilePath,
+    init,
+    run,
+    pause,
+    resume,
+    cleanup    
 };
 
-VBoxClient::Service *VBoxClient::GetSeamlessService()
-{
-    return new SeamlessService;
-}
+struct VBCLSERVICE **VBClGetSeamlessService()
+{
+    struct SEAMLESSSERVICE *pService =
+        (struct SEAMLESSSERVICE *)RTMemAlloc(sizeof(*pService));
+
+    if (!pService)
+        VBClFatalError(("Out of memory\n"));
+    pService->pInterface = &vbclSeamlessInterface;
+    pService->magic = SEAMLESSSERVICE_MAGIC;
+    new(&pService->mSeamless) SeamlessMain();
+    pService->mIsInitialised = false;
+    return &pService->pInterface;
+}
Index: /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp	(revision 52561)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp	(revision 52562)
@@ -25,4 +25,11 @@
 
 static RTSEMEVENT eventSem;
+
+/** Exit with a fatal error. */
+void vbclFatalError(char *pszMessage)
+{
+    RTPrintf("Fatal error: %s", pszMessage);
+    exit(1);
+}
 
 int VbglR3SeamlessSendRects(uint32_t cRects, PRTRECT pRects)
