VirtualBox

Changeset 52562 in vbox


Ignore:
Timestamp:
Sep 2, 2014 6:28:04 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95827
Message:

Additions/x11/VBoxClient: clean-up and some C++ to C conversion.

Location:
trunk/src/VBox/Additions/x11/VBoxClient
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/x11/VBoxClient/VBoxClient.h

    r52231 r52562  
    2424
    2525/** Exit with a fatal error. */
    26 #define FatalError(format) \
     26#define VBClFatalError(format) \
    2727do { \
    2828    char *pszMessage = RTStrAPrintf2 format; \
    2929    LogRel(format); \
    30     doFatalError(pszMessage); \
     30    vbclFatalError(pszMessage); \
    3131} while(0)
    3232
    3333/** Exit with a fatal error. */
    34 extern void doFatalError(char *pszMessage);
     34extern void vbclFatalError(char *pszMessage);
    3535
    36 /** Namespace for VBoxClient-specific things */
    37 namespace VBoxClient {
     36/** Call clean-up for the current service and exit. */
     37extern void VBClCleanUp();
    3838
    39 /** A simple class describing a service.  VBoxClient will run exactly one
     39/** A simple interface describing a service.  VBoxClient will run exactly one
    4040 * service per invocation. */
    41 class Service : public RTCNonCopyable
     41struct VBCLSERVICE
    4242{
    43 public:
    4443    /** Get the services default path to pidfile, relative to $HOME */
    4544    /** @todo Should this also have a component relative to the X server number?
    4645     */
    47     virtual const char *getPidFilePath() = 0;
     46    const char *(*getPidFilePath)(void);
    4847    /** Special initialisation, if needed.  @a pause and @a resume are
    4948     * guaranteed not to be called until after this returns. */
    50     virtual int init() { return VINF_SUCCESS; }
     49    int (*init)(struct VBCLSERVICE **ppInterface);
    5150    /** Run the service main loop */
    52     virtual int run(bool fDaemonised = false) = 0;
     51    int (*run)(struct VBCLSERVICE **ppInterface, bool fDaemonised);
    5352    /** Pause the service loop.  This must be safe to call on a different thread
    5453     * and potentially before @a run is or after it exits.
     
    5756     * is available then @a pause or @a resume will be called as soon as it starts
    5857     * up. */
    59     virtual int pause() { return VINF_SUCCESS; }
     58    int (*pause)(struct VBCLSERVICE **ppInterface);
    6059    /** Resume after pausing.  The same applies here as for @a pause. */
    61     virtual int resume() { return VINF_SUCCESS; }
     60    int (*resume)(struct VBCLSERVICE **ppInterface);
    6261    /** Clean up any global resources before we shut down hard.  The last calls
    6362     * to @a pause and @a resume are guaranteed to finish before this is called.
    6463     */
    65     virtual void cleanup() = 0;
    66     /** Virtual destructor.  Not used */
    67     virtual ~Service() {}
     64    void (*cleanup)(struct VBCLSERVICE **ppInterface);
    6865};
    6966
    70 extern Service *GetClipboardService();
    71 extern Service *GetSeamlessService();
    72 extern Service *GetDisplayService();
    73 extern Service *GetHostVersionService();
     67/** Default handler for various struct VBCLSERVICE member functions. */
     68static int VBClServiceDefaultHandler(struct VBCLSERVICE **pSelf)
     69{
     70    return VINF_SUCCESS;
     71}
     72
     73/** Default handler for the struct VBCLSERVICE clean-up member function.
     74 * Usually used because the service is cleaned up automatically when the user
     75 * process/X11 exits. */
     76static void VBClServiceDefaultCleanup(struct VBCLSERVICE **ppInterface)
     77{
     78    NOREF(ppInterface);
     79}
     80
     81extern struct VBCLSERVICE **VBClGetClipboardService();
     82extern struct VBCLSERVICE **VBClGetSeamlessService();
     83extern struct VBCLSERVICE **VBClGetDisplayService();
     84extern struct VBCLSERVICE **VBClGetHostVersionService();
    7485#ifdef VBOX_WITH_DRAG_AND_DROP
    75 extern Service *GetDragAndDropService();
     86extern struct VBCLSERVICE **VBClGetDragAndDropService();
    7687#endif /* VBOX_WITH_DRAG_AND_DROP */
    7788
    78 extern void CleanUp();
    79 
    80 } /* namespace VBoxClient */
    81 
    8289#endif /* !___vboxclient_vboxclient_h */
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp

    r48945 r52562  
    278278}
    279279
    280 class ClipboardService : public VBoxClient::Service
    281 {
    282 public:
    283     virtual const char *getPidFilePath()
    284     {
    285         return ".vboxclient-clipboard.pid";
    286     }
    287     virtual int run(bool fDaemonised /* = false */)
    288     {
    289         int rc = vboxClipboardConnect();
    290         if (RT_SUCCESS(rc))
    291             rc = vboxClipboardMain();
    292         if (RT_FAILURE(rc))
    293             LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc));
    294         return rc;
    295     }
    296     virtual void cleanup()
    297     {
    298         /* Nothing to do. */
    299     }
     280static const char *getPidFilePath()
     281{
     282    return ".vboxclient-clipboard.pid";
     283}
     284
     285static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
     286{
     287    int rc = vboxClipboardConnect();
     288
     289    NOREF(ppInterface);
     290    if (RT_SUCCESS(rc))
     291        rc = vboxClipboardMain();
     292    if (RT_FAILURE(rc))
     293        LogRelFunc(("guest clipboard service terminated abnormally: return code %Rrc\n", rc));
     294    return rc;
     295}
     296
     297struct VBCLSERVICE vbclClipboardInterface =
     298{
     299    getPidFilePath,
     300    VBClServiceDefaultHandler, /* init */
     301    run,
     302    VBClServiceDefaultHandler, /* pause */
     303    VBClServiceDefaultHandler, /* resume */
     304    VBClServiceDefaultCleanup   
    300305};
    301306
    302 VBoxClient::Service *VBoxClient::GetClipboardService()
    303 {
    304     return new ClipboardService;
    305 }
     307struct CLIPBOARDSERVICE
     308{
     309    struct VBCLSERVICE *pInterface;
     310};
     311
     312struct VBCLSERVICE **VBClGetClipboardService()
     313{
     314    struct CLIPBOARDSERVICE *pService =
     315        (struct CLIPBOARDSERVICE *)RTMemAlloc(sizeof(*pService));
     316
     317    if (!pService)
     318        VBClFatalError(("Out of memory\n"));
     319    pService->pInterface = &vbclClipboardInterface;
     320    return &pService->pInterface;
     321}
  • trunk/src/VBox/Additions/x11/VBoxClient/display.cpp

    r52231 r52562  
    6464    int rc = VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS);
    6565    if (RT_FAILURE(rc))
    66         FatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));
     66        VBClFatalError(("Failed to unset graphics capability, rc=%Rrc.\n", rc));
    6767    rc = VbglR3SetMouseStatus(VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);
    6868    if (RT_FAILURE(rc))
    69         FatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
     69        VBClFatalError(("Failed to unset mouse status, rc=%Rrc.\n", rc));
    7070    rc = VbglR3CtlFilterMask(0,  VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED
    7171                                | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST);
    7272    if (RT_FAILURE(rc))
    73         FatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
     73        VBClFatalError(("Failed to unset filter mask, rc=%Rrc.\n", rc));
    7474    return VINF_SUCCESS;
    7575}
     
    8282                                 | VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0);
    8383    if (RT_FAILURE(rc))
    84         FatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));
     84        VBClFatalError(("Failed to set filter mask, rc=%Rrc.\n", rc));
    8585    rc = VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0);
    8686    if (RT_FAILURE(rc))
    87         FatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));
     87        VBClFatalError(("Failed to set graphics capability, rc=%Rrc.\n", rc));
    8888    rc = VbglR3SetMouseStatus(0);
    8989    if (RT_FAILURE(rc))
    90         FatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));
     90        VBClFatalError(("Failed to set mouse status, rc=%Rrc.\n", rc));
    9191    return VINF_SUCCESS;
    9292}
     
    106106    status = system(pState->pcszXrandr);
    107107    if (WEXITSTATUS(status) != 0)  /* Utility or extension not available. */
    108         FatalError(("Failed to execute the xrandr utility.\n"));
     108        VBClFatalError(("Failed to execute the xrandr utility.\n"));
    109109    RTStrPrintf(szCommand, sizeof(szCommand), "%s --q12", pState->pcszXrandr);
    110110    status = system(szCommand);
     
    130130                                                * sizeof(*pState->paSizeHints));
    131131        if (!pState->paSizeHints)
    132             FatalError(("Failed to re-allocate size hint memory.\n"));
     132            VBClFatalError(("Failed to re-allocate size hint memory.\n"));
    133133        for (i = pState->cSizeHints; i < iDisplay + 1; ++i)
    134134            pState->paSizeHints[i] = 0;
     
    151151        status = system(szCommand);
    152152        if (WEXITSTATUS(status) != 0)
    153             FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     153            VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    154154    }
    155155    else
     
    164164            status = system(szCommand);
    165165            if (WEXITSTATUS(status) != 0)
    166                 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     166                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    167167        }
    168168        if ((!fSetPosition || fEnabled) && cx != 0 && cy != 0)
     
    173173            status = system(szCommand);
    174174            if (WEXITSTATUS(status) != 0)
    175                 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     175                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    176176        }
    177177        if (!fEnabled)
     
    183183            status = system(szCommand);
    184184            if (WEXITSTATUS(status) != 0)
    185                 FatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
     185                VBClFatalError(("Failed to execute \\\"%s\\\".\n", szCommand));
    186186        }
    187187    }
     
    206206    rc = VbglR3VideoModeGetHighestSavedScreen(&cScreens);
    207207    if (RT_FAILURE(rc))
    208         FatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n",
     208        VBClFatalError(("Failed to get the number of saved screen modes, rc=%Rrc\n",
    209209                    rc));
    210210    for (i = 0; i < RT_MAX(cScreens + 1, 8); ++i)
     
    216216                                     &fEnabled);
    217217        if (RT_SUCCESS(rc) && i > cScreens) /* Sanity */
    218             FatalError(("Internal error retrieving the number of saved screen modes.\n"));
     218            VBClFatalError(("Internal error retrieving the number of saved screen modes.\n"));
    219219        if (RT_SUCCESS(rc))
    220220            setModeX11(pState, cx, cy, cBPP, i, x, y, fEnabled,
     
    230230        while(rc == VERR_INTERRUPTED);
    231231        if (RT_FAILURE(rc))  /* VERR_NO_MEMORY? */
    232             FatalError(("event wait failed, rc=%Rrc\n", rc));
     232            VBClFatalError(("event wait failed, rc=%Rrc\n", rc));
    233233        if (fEvents & VMMDEV_EVENT_MOUSE_CAPABILITIES_CHANGED)
    234234        {
     
    262262            {
    263263                if (rc != VERR_NOT_IMPLEMENTED)
    264                     FatalError(("Failed to get display change request, rc=%Rrc\n",
     264                    VBClFatalError(("Failed to get display change request, rc=%Rrc\n",
    265265                                rc));
    266266                fSetPosition = false;
     
    276276                                fEnabled));
    277277            if (RT_FAILURE(rc))
    278                 FatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));
     278                VBClFatalError(("Failed to retrieve size hint, rc=%Rrc\n", rc));
    279279            if (iDisplay > INT32_MAX)
    280                 FatalError(("Received a size hint for too high display number %u\n",
     280                VBClFatalError(("Received a size hint for too high display number %u\n",
    281281                            (unsigned) iDisplay));
    282282            rc = VbglR3SeamlessGetLastEvent(&Mode);
    283283            if (RT_FAILURE(rc))
    284                 FatalError(("Failed to check seamless mode, rc=%Rrc\n", rc));
     284                VBClFatalError(("Failed to check seamless mode, rc=%Rrc\n", rc));
    285285            if (Mode == VMMDev_Seamless_Disabled)
    286286            {
     
    290290                    && rc != VERR_HGCM_SERVICE_NOT_FOUND
    291291                    && rc != VERR_NOT_IMPLEMENTED /* No HGCM */)
    292                     FatalError(("Failed to save size hint, rc=%Rrc\n", rc));
     292                    VBClFatalError(("Failed to save size hint, rc=%Rrc\n", rc));
    293293            }
    294294            setModeX11(pState, cx, cy, cBPP, iDisplay, x, y, fEnabled,
     
    298298}
    299299
    300 class DisplayService : public VBoxClient::Service
    301 {
     300/** Display magic number, start of a UUID. */
     301#define DISPLAYSERVICE_MAGIC 0xf0029993
     302
     303/** VBoxClient service class wrapping the logic for the display service while
     304 *  the main VBoxClient code provides the daemon logic needed by all services.
     305 */
     306struct DISPLAYSERVICE
     307{
     308    /** The service interface. */
     309    struct VBCLSERVICE *pInterface;
     310    /** Magic number for sanity checks. */
     311    uint32_t magic;
     312    /** State related to the X server. */
    302313    struct x11State mState;
     314    /** Are we initialised yet? */
    303315    bool mfInit;
    304 public:
    305     virtual const char *getPidFilePath()
    306     {
    307         return ".vboxclient-display.pid";
    308     }
    309     virtual int init()
    310     {
    311         int rc;
    312        
    313         if (mfInit)
    314             return VERR_WRONG_ORDER;
    315         rc = initX11(&mState);
    316         if (RT_FAILURE(rc))
    317             return rc;
    318         rc = enableEventsAndCaps();
    319         if (RT_SUCCESS(rc))
    320             mfInit = true;
     316};
     317
     318static const char *getPidFilePath()
     319{
     320    return ".vboxclient-display.pid";
     321}
     322
     323static struct DISPLAYSERVICE *getClassFromInterface(struct VBCLSERVICE **
     324                                                         ppInterface)
     325{
     326    struct DISPLAYSERVICE *pSelf = (struct DISPLAYSERVICE *)ppInterface;
     327    if (pSelf->magic != DISPLAYSERVICE_MAGIC)
     328        VBClFatalError(("Bad display service object!\n"));
     329    return pSelf;
     330}
     331
     332static int init(struct VBCLSERVICE **ppInterface)
     333{
     334    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
     335    int rc;
     336   
     337    if (pSelf->mfInit)
     338        return VERR_WRONG_ORDER;
     339    rc = initX11(&pSelf->mState);
     340    if (RT_FAILURE(rc))
    321341        return rc;
    322     }
    323     virtual int run(bool fDaemonised /* = false */)
    324     {
    325         if (!mfInit)
    326             return VERR_WRONG_ORDER;
    327         runDisplay(&mState);
    328         return VERR_INTERNAL_ERROR;  /* "Should never reach here." */
    329     }
    330     virtual int pause()
    331     {
    332         if (!mfInit)
    333             return VERR_WRONG_ORDER;
    334         return disableEventsAndCaps();
    335     }
    336     virtual int resume()
    337     {
    338         if (!mfInit)
    339             return VERR_WRONG_ORDER;
    340         return enableEventsAndCaps();
    341     }
    342     virtual void cleanup()
    343     {
    344         disableEventsAndCaps();
    345     }
    346     DisplayService() { mfInit = false; }
     342    rc = enableEventsAndCaps();
     343    if (RT_SUCCESS(rc))
     344        pSelf->mfInit = true;
     345    return rc;
     346}
     347
     348static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
     349{
     350    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
     351
     352    if (!pSelf->mfInit)
     353        return VERR_WRONG_ORDER;
     354    runDisplay(&pSelf->mState);
     355    return VERR_INTERNAL_ERROR;  /* "Should never reach here." */
     356}
     357
     358static int pause(struct VBCLSERVICE **ppInterface)
     359{
     360    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
     361
     362    if (!pSelf->mfInit)
     363        return VERR_WRONG_ORDER;
     364    return disableEventsAndCaps();
     365}
     366
     367static int resume(struct VBCLSERVICE **ppInterface)
     368{
     369    struct DISPLAYSERVICE *pSelf = getClassFromInterface(ppInterface);
     370
     371    if (!pSelf->mfInit)
     372        return VERR_WRONG_ORDER;
     373    return enableEventsAndCaps();
     374}
     375
     376static void cleanup(struct VBCLSERVICE **ppInterface)
     377{
     378    NOREF(ppInterface);
     379    disableEventsAndCaps();
     380}
     381
     382struct VBCLSERVICE vbclDisplayInterface =
     383{
     384    getPidFilePath,
     385    init,
     386    run,
     387    pause,
     388    resume,
     389    cleanup   
    347390};
    348391
    349 VBoxClient::Service *VBoxClient::GetDisplayService()
    350 {
    351     return new DisplayService;
    352 }
     392struct VBCLSERVICE **VBClGetDisplayService()
     393{
     394    struct DISPLAYSERVICE *pService =
     395        (struct DISPLAYSERVICE *)RTMemAlloc(sizeof(*pService));
     396
     397    if (!pService)
     398        VBClFatalError(("Out of memory\n"));
     399    pService->pInterface = &vbclDisplayInterface;
     400    pService->magic = DISPLAYSERVICE_MAGIC;
     401    pService->mfInit = false;
     402    return &pService->pInterface;
     403}
  • trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp

    r51556 r52562  
    441441 ******************************************************************************/
    442442
    443 class DragAndDropService : public VBoxClient::Service
     443class DragAndDropService
    444444{
    445445public:
     
    453453    {}
    454454
    455     virtual const char *getPidFilePath() { return ".vboxclient-draganddrop.pid"; }
    456 
    457     virtual int run(bool fDaemonised = false);
    458 
    459     virtual void cleanup(void)
    460     {
    461         /* Nothing to do, everything should be cleaned up automatically when the
    462          * user process/X11 client exits. */
    463     };
     455    int run(bool fDaemonised = false);
    464456
    465457private:
     
    23872379}
    23882380
     2381/** Drag and drop magic number, start of a UUID. */
     2382#define DRAGANDDROPSERVICE_MAGIC 0x67c97173
     2383
     2384/** VBoxClient service class wrapping the logic for the service while
     2385 *  the main VBoxClient code provides the daemon logic needed by all services.
     2386 */
     2387struct DRAGANDDROPSERVICE
     2388{
     2389    /** The service interface. */
     2390    struct VBCLSERVICE *pInterface;
     2391    /** Magic number for sanity checks. */
     2392    uint32_t magic;
     2393    /** Service object. */
     2394    DragAndDropService mDragAndDrop;
     2395};
     2396
     2397static const char *getPidFilePath()
     2398{
     2399    return ".vboxclient-draganddrop.pid";
     2400}
     2401
     2402static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
     2403{
     2404    struct DRAGANDDROPSERVICE *pSelf = (struct DRAGANDDROPSERVICE *)ppInterface;
     2405
     2406    if (pSelf->magic != DRAGANDDROPSERVICE_MAGIC)
     2407        VBClFatalError(("Bad display service object!\n"));
     2408    return pSelf->mDragAndDrop.run(fDaemonised);
     2409}
     2410
     2411struct VBCLSERVICE vbclDragAndDropInterface =
     2412{
     2413    getPidFilePath,
     2414    VBClServiceDefaultHandler, /* init */
     2415    run,
     2416    VBClServiceDefaultHandler, /* pause */
     2417    VBClServiceDefaultHandler, /* resume */
     2418    VBClServiceDefaultCleanup   
     2419};
     2420
    23892421/* Static factory */
    2390 VBoxClient::Service *VBoxClient::GetDragAndDropService(void)
    2391 {
    2392     DragAndDropService *pService = new DragAndDropService();
    2393     return pService;
    2394 }
    2395 
     2422struct VBCLSERVICE **VBClGetDragAndDropService(void)
     2423{
     2424    struct DRAGANDDROPSERVICE *pService =
     2425        (struct DRAGANDDROPSERVICE *)RTMemAlloc(sizeof(*pService));
     2426
     2427    if (!pService)
     2428        VBClFatalError(("Out of memory\n"));
     2429    pService->pInterface = &vbclDragAndDropInterface;
     2430    pService->magic = DRAGANDDROPSERVICE_MAGIC;
     2431    new(&pService->mDragAndDrop) DragAndDropService();
     2432    return &pService->pInterface;
     2433}
     2434
  • trunk/src/VBox/Additions/x11/VBoxClient/hostversion.cpp

    r44529 r52562  
    1717#include <iprt/assert.h>
    1818#include <iprt/err.h>
     19#include <iprt/mem.h>
    1920#include <iprt/ldr.h>
    2021#include <iprt/string.h>
     
    3233#include "VBoxClient.h"
    3334
    34 class HostVersionService : public VBoxClient::Service
    35 {
    36 
    37 public:
    38 
    39     virtual const char *getPidFilePath()
    40     {
    41         return ".vboxclient-hostversion.pid";
    42     }
    43 
    44     virtual int showNotify(const char *pcHeader, const char *pcBody)
    45     {
    46         int rc;
     35static const char *getPidFilePath()
     36{
     37    return ".vboxclient-hostversion.pid";
     38}
     39
     40static int showNotify(const char *pcHeader, const char *pcBody)
     41{
     42    int rc;
    4743# ifdef VBOX_WITH_DBUS
    48         DBusConnection *conn;
    49         DBusMessage* msg = NULL;
    50         conn = dbus_bus_get (DBUS_BUS_SESSON, NULL);
    51         if (conn == NULL)
    52         {
    53             LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
     44    DBusConnection *conn;
     45    DBusMessage* msg = NULL;
     46    conn = dbus_bus_get (DBUS_BUS_SESSON, NULL);
     47    if (conn == NULL)
     48    {
     49        LogRelFlowFunc(("Could not retrieve D-BUS session bus!\n"));
     50        rc = VERR_INVALID_HANDLE;
     51    }
     52    else
     53    {
     54        msg = dbus_message_new_method_call("org.freedesktop.Notifications",
     55                                           "/org/freedesktop/Notifications",
     56                                           "org.freedesktop.Notifications",
     57                                           "Notify");
     58        if (msg == NULL)
     59        {
     60            LogRel(("Could not create D-BUS message!\n"));
    5461            rc = VERR_INVALID_HANDLE;
    5562        }
    5663        else
    57         {
    58             msg = dbus_message_new_method_call("org.freedesktop.Notifications",
    59                                                "/org/freedesktop/Notifications",
    60                                                "org.freedesktop.Notifications",
    61                                                "Notify");
    62             if (msg == NULL)
     64            rc = VINF_SUCCESS;
     65    }
     66    if (RT_SUCCESS(rc))
     67    {
     68        uint32_t msg_replace_id = 0;
     69        const char *msg_app = "VBoxClient";
     70        const char *msg_icon = "";
     71        const char *msg_summary = pcHeader;
     72        const char *msg_body = pcBody;
     73        int32_t msg_timeout = -1;           /* Let the notification server decide */
     74
     75        DBusMessageIter iter;
     76        DBusMessageIter array;
     77        DBusMessageIter dict;
     78        DBusMessageIter value;
     79        DBusMessageIter variant;
     80        DBusMessageIter data;
     81
     82        /* Format: UINT32 org.freedesktop.Notifications.Notify
     83         *         (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body,
     84         *          ARRAY actions, DICT hints, INT32 expire_timeout)
     85         */
     86        dbus_message_iter_init_append(msg,&iter);
     87        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app);
     88        dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id);
     89        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon);
     90        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary);
     91        dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body);
     92        dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
     93        dbus_message_iter_close_container(&iter,&array);
     94        dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array);
     95        dbus_message_iter_close_container(&iter,&array);
     96        dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout);
     97
     98        DBusError err;
     99        dbus_error_init(&err);
     100
     101        DBusMessage *reply;
     102        reply = dbus_connection_send_with_reply_and_block(conn, msg,
     103            30 * 1000 /* 30 seconds timeout */, &err);
     104        if (dbus_error_is_set(&err))
     105        {
     106            LogRel(("D-BUS returned an error while sending the notification: %s", err.message));
     107        }
     108        else if (reply)
     109        {
     110            dbus_connection_flush(conn);
     111            dbus_message_unref(reply);
     112        }
     113        if (dbus_error_is_set(&err))
     114            dbus_error_free(&err);
     115    }
     116    if (msg != NULL)
     117        dbus_message_unref(msg);
     118# else
     119    /* TODO: Implement me */
     120    rc = VINF_SUCCESS;
     121# endif /* VBOX_WITH_DBUS */
     122    return rc;
     123}
     124
     125/** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
     126          notification stuff, since this is very similar to the VBoxTray code. */
     127static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
     128{
     129    int rc;
     130    LogFlowFunc(("\n"));
     131
     132    NOREF(ppInterface);
     133    /* Because we need desktop notifications to be displayed, wait
     134     * some time to make the desktop environment load (as a work around). */
     135    if (fDaemonised)
     136        RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
     137
     138# ifdef VBOX_WITH_DBUS
     139    rc = RTDBusLoadLib();
     140    if (RT_FAILURE(rc))
     141        LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
     142# else
     143    rc = VERR_NOT_IMPLEMENTED;
     144# endif /* VBOX_WITH_DBUS */
     145
     146# ifdef VBOX_WITH_GUEST_PROPS
     147    uint32_t uGuestPropSvcClientID;
     148    if (RT_SUCCESS(rc))
     149    {
     150        rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
     151        if (RT_FAILURE(rc))
     152            LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
     153    }
     154
     155    if (RT_SUCCESS(rc))
     156    {
     157        char *pszHostVersion;
     158        char *pszGuestVersion;
     159        bool bUpdate;
     160
     161        rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
     162        if (RT_SUCCESS(rc))
     163        {
     164            if (bUpdate)
    63165            {
    64                 LogRel(("Could not create D-BUS message!\n"));
    65                 rc = VERR_INVALID_HANDLE;
    66             }
    67             else
    68                 rc = VINF_SUCCESS;
    69         }
    70         if (RT_SUCCESS(rc))
    71         {
    72             uint32_t msg_replace_id = 0;
    73             const char *msg_app = "VBoxClient";
    74             const char *msg_icon = "";
    75             const char *msg_summary = pcHeader;
    76             const char *msg_body = pcBody;
    77             int32_t msg_timeout = -1;           /* Let the notification server decide */
    78 
    79             DBusMessageIter iter;
    80             DBusMessageIter array;
    81             DBusMessageIter dict;
    82             DBusMessageIter value;
    83             DBusMessageIter variant;
    84             DBusMessageIter data;
    85 
    86             /* Format: UINT32 org.freedesktop.Notifications.Notify
    87              *         (STRING app_name, UINT32 replaces_id, STRING app_icon, STRING summary, STRING body,
    88              *          ARRAY actions, DICT hints, INT32 expire_timeout)
    89              */
    90             dbus_message_iter_init_append(msg,&iter);
    91             dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_app);
    92             dbus_message_iter_append_basic(&iter,DBUS_TYPE_UINT32,&msg_replace_id);
    93             dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_icon);
    94             dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_summary);
    95             dbus_message_iter_append_basic(&iter,DBUS_TYPE_STRING,&msg_body);
    96             dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING,&array);
    97             dbus_message_iter_close_container(&iter,&array);
    98             dbus_message_iter_open_container(&iter,DBUS_TYPE_ARRAY,"{sv}",&array);
    99             dbus_message_iter_close_container(&iter,&array);
    100             dbus_message_iter_append_basic(&iter,DBUS_TYPE_INT32,&msg_timeout);
    101 
    102             DBusError err;
    103             dbus_error_init(&err);
    104 
    105             DBusMessage *reply;
    106             reply = dbus_connection_send_with_reply_and_block(conn, msg,
    107                 30 * 1000 /* 30 seconds timeout */, &err);
    108             if (dbus_error_is_set(&err))
    109             {
    110                 LogRel(("D-BUS returned an error while sending the notification: %s", err.message));
    111             }
    112             else if (reply)
    113             {
    114                 dbus_connection_flush(conn);
    115                 dbus_message_unref(reply);
    116             }
    117             if (dbus_error_is_set(&err))
    118                 dbus_error_free(&err);
    119         }
    120         if (msg != NULL)
    121             dbus_message_unref(msg);
    122 # else
    123         /* TODO: Implement me */
    124         rc = VINF_SUCCESS;
    125 # endif /* VBOX_WITH_DBUS */
    126         return rc;
    127     }
    128 
    129     /** @todo Move this part in VbglR3 and just provide a callback for the platform-specific
    130               notification stuff, since this is very similar to the VBoxTray code. */
    131     virtual int run(bool fDaemonised /* = false */)
    132     {
    133         int rc;
    134         LogFlowFunc(("\n"));
    135 
    136         /* Because we need desktop notifications to be displayed, wait
    137          * some time to make the desktop environment load (as a work around). */
    138         if (fDaemonised)
    139             RTThreadSleep(30 * 1000 /* Wait 30 seconds */);
    140 
    141 # ifdef VBOX_WITH_DBUS
    142         rc = RTDBusLoadLib();
    143         if (RT_FAILURE(rc))
    144             LogRel(("VBoxClient: D-Bus seems not to be installed; no host version check/notification done.\n"));
    145 # else
    146         rc = VERR_NOT_IMPLEMENTED;
    147 # endif /* VBOX_WITH_DBUS */
    148 
    149 # ifdef VBOX_WITH_GUEST_PROPS
    150         uint32_t uGuestPropSvcClientID;
    151         if (RT_SUCCESS(rc))
    152         {
    153             rc = VbglR3GuestPropConnect(&uGuestPropSvcClientID);
    154             if (RT_FAILURE(rc))
    155                 LogRel(("VBoxClient: Cannot connect to guest property service while chcking for host version! rc = %Rrc\n", rc));
    156         }
    157 
    158         if (RT_SUCCESS(rc))
    159         {
    160             char *pszHostVersion;
    161             char *pszGuestVersion;
    162             bool bUpdate;
    163 
    164             rc = VbglR3HostVersionCheckForUpdate(uGuestPropSvcClientID, &bUpdate, &pszHostVersion, &pszGuestVersion);
    165             if (RT_SUCCESS(rc))
    166             {
    167                 if (bUpdate)
    168                 {
    169                     char szMsg[1024];
    170                     char szTitle[64];
    171 
    172                     /** @todo add some translation macros here */
    173                     RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
     166                char szMsg[1024];
     167                char szTitle[64];
     168
     169                /** @todo add some translation macros here */
     170                RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions update available!");
    174171#ifndef VBOX_OSE
    175                     RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
    176                                                       "We recommend updating to the latest version (%s) by choosing the "
    177                                                       "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
     172                RTStrPrintf(szMsg, sizeof(szMsg), "Your guest is currently running the Guest Additions version %s. "
     173                                                  "We recommend updating to the latest version (%s) by choosing the "
     174                                                  "install option from the Devices menu.", pszGuestVersion, pszHostVersion);
    178175#else
    179176/* This is the message which appears for non-Oracle builds of the
    180  * Guest Additions.  Distributors are encouraged to customise this. */
    181                     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);
     177* Guest Additions.  Distributors are encouraged to customise this. */
     178                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);
    182179#endif
    183                     rc = showNotify(szTitle, szMsg);
    184                     LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
    185                     if (RT_FAILURE(rc))
    186                         LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
    187                 }
    188 
    189                 /* Store host version to not notify again */
    190                 rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);
    191 
    192                 VbglR3GuestPropReadValueFree(pszHostVersion);
    193                 VbglR3GuestPropReadValueFree(pszGuestVersion);
     180                rc = showNotify(szTitle, szMsg);
     181                LogRel(("VBoxClient: VirtualBox Guest Additions update available!"));
     182                if (RT_FAILURE(rc))
     183                    LogRel(("VBoxClient: Could not show version notifier tooltip! rc = %d\n", rc));
    194184            }
    195             VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
    196         }
     185
     186            /* Store host version to not notify again */
     187            rc = VbglR3HostVersionLastCheckedStore(uGuestPropSvcClientID, pszHostVersion);
     188
     189            VbglR3GuestPropReadValueFree(pszHostVersion);
     190            VbglR3GuestPropReadValueFree(pszGuestVersion);
     191        }
     192        VbglR3GuestPropDisconnect(uGuestPropSvcClientID);
     193    }
    197194# endif /* VBOX_WITH_GUEST_PROPS */
    198         LogFlowFunc(("returning %Rrc\n", rc));
    199         return rc;
    200     }
    201 
    202     virtual void cleanup()
    203     {
    204 
    205     }
     195    LogFlowFunc(("returning %Rrc\n", rc));
     196    return rc;
     197}
     198
     199struct VBCLSERVICE vbclHostVersionInterface =
     200{
     201    getPidFilePath,
     202    VBClServiceDefaultHandler, /* init */
     203    run,
     204    VBClServiceDefaultHandler, /* pause */
     205    VBClServiceDefaultHandler, /* resume */
     206    VBClServiceDefaultCleanup   
    206207};
    207208
     209struct HOSTVERSIONSERVICE
     210{
     211    struct VBCLSERVICE *pInterface;
     212};
     213
    208214/* Static factory */
    209 VBoxClient::Service *VBoxClient::GetHostVersionService()
    210 {
    211     return new HostVersionService;
    212 }
    213 
     215struct VBCLSERVICE **VBClGetHostVersionService()
     216{
     217    struct HOSTVERSIONSERVICE *pService =
     218        (struct HOSTVERSIONSERVICE *)RTMemAlloc(sizeof(*pService));
     219
     220    if (!pService)
     221        VBClFatalError(("Out of memory\n"));
     222    pService->pInterface = &vbclHostVersionInterface;
     223    return &pService->pInterface;
     224}
     225
  • trunk/src/VBox/Additions/x11/VBoxClient/main.cpp

    r52231 r52562  
    4848/** Object representing the service we are running.  This has to be global
    4949 * so that the cleanup routine can access it. */
    50 VBoxClient::Service *g_pService;
     50struct VBCLSERVICE **g_pService;
    5151/** The name of our pidfile.  It is global for the benefit of the cleanup
    5252 * routine. */
     
    6262
    6363/** Exit with a fatal error. */
    64 void doFatalError(char *pszMessage)
     64void vbclFatalError(char *pszMessage)
    6565{
    6666    char *pszCommand;
     
    7777/** Clean up if we get a signal or something.  This is extern so that we
    7878 * can call it from other compilation units. */
    79 void VBoxClient::CleanUp()
     79void VBClCleanUp()
    8080{
    8181    /* We never release this, as we end up with a call to exit(3) which is not
     
    8989    }
    9090    if (g_pService)
    91         g_pService->cleanup();
     91        (*g_pService)->cleanup(g_pService);
    9292    if (g_szPidFile[0] && g_hPidFile)
    9393        VbglR3ClosePidFile(g_szPidFile, g_hPidFile);
     
    104104    /** Disable seamless mode */
    105105    RTPrintf(("VBoxClient: terminating...\n"));
    106     VBoxClient::CleanUp();
     106    VBClCleanUp();
    107107}
    108108
     
    126126{
    127127    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"));
    128     VBoxClient::CleanUp();
     128    VBClCleanUp();
    129129    return 0;  /* We should never reach this. */
    130130}
     
    200200        pcszStage = "asking service to pause or resume";
    201201        if (cTTY == cVT)
    202             rc = g_pService->resume();
     202            rc = (*g_pService)->resume(g_pService);
    203203        else
    204             rc = g_pService->pause();
     204            rc = (*g_pService)->pause(g_pService);
    205205        if (RT_FAILURE(rc))
    206206            break;
     
    214214        if (RTCritSectIsOwner(&g_critSect))
    215215            RTCritSectLeave(&g_critSect);
    216         VBoxClient::CleanUp();
     216        VBClCleanUp();
    217217    }
    218218}
     
    273273        {
    274274            LogRel(("Monitor thread: poll failed, stopping.\n"));
    275             VBoxClient::CleanUp();
     275            VBClCleanUp();
    276276        }
    277277    }
     
    397397            if (g_pService)
    398398                break;
    399             g_pService = VBoxClient::GetClipboardService();
     399            g_pService = VBClGetClipboardService();
    400400        }
    401401        else if (!strcmp(argv[i], "--display"))
     
    403403            if (g_pService)
    404404                break;
    405             g_pService = VBoxClient::GetDisplayService();
     405            g_pService = VBClGetDisplayService();
    406406        }
    407407        else if (!strcmp(argv[i], "--seamless"))
     
    409409            if (g_pService)
    410410                break;
    411             g_pService = VBoxClient::GetSeamlessService();
     411            g_pService = VBClGetSeamlessService();
    412412        }
    413413        else if (!strcmp(argv[i], "--checkhostversion"))
     
    415415            if (g_pService)
    416416                break;
    417             g_pService = VBoxClient::GetHostVersionService();
     417            g_pService = VBClGetHostVersionService();
    418418        }
    419419#ifdef VBOX_WITH_DRAG_AND_DROP
     
    422422            if (g_pService)
    423423                break;
    424             g_pService = VBoxClient::GetDragAndDropService();
     424            g_pService = VBClGetDragAndDropService();
    425425        }
    426426#endif /* VBOX_WITH_DRAG_AND_DROP */
     
    455455        pcszStage = "Creating pid-file path";
    456456        rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile),
    457                           g_pService->getPidFilePath());
     457                          (*g_pService)->getPidFilePath());
    458458        if (RT_FAILURE(rc))
    459459            break;
     
    477477        XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
    478478        pcszStage = "Initialising service";
    479         rc = g_pService->init();
     479        rc = (*g_pService)->init(g_pService);
    480480    } while (0);
    481481    if (RT_FAILURE(rc))
     
    492492                 rc));
    493493    else
    494         g_pService->run(fDaemonise);  /* Should never return. */
    495     VBoxClient::CleanUp();
     494        (*g_pService)->run(g_pService, fDaemonise);  /* Should never return. */
     495    VBClCleanUp();
    496496    return 1;
    497497}
  • trunk/src/VBox/Additions/x11/VBoxClient/seamless.cpp

    r50637 r52562  
    2727#include <VBox/VBoxGuestLib.h>
    2828#include <iprt/err.h>
     29#include <iprt/mem.h>
    2930
    3031#include "VBoxClient.h"
    3132#include "seamless.h"
     33
     34#include <new>
    3235
    3336SeamlessMain::SeamlessMain(void)
     
    316319}
    317320
     321/** Service magic number, start of a UUID. */
     322#define SEAMLESSSERVICE_MAGIC 0xd28ba727
     323
    318324/** VBoxClient service class wrapping the logic for the seamless service while
    319325 *  the main VBoxClient code provides the daemon logic needed by all services.
    320326 */
    321 class SeamlessService : public VBoxClient::Service
    322 {
    323 private:
     327struct SEAMLESSSERVICE
     328{
     329    /** The service interface. */
     330    struct VBCLSERVICE *pInterface;
     331    /** Magic number for sanity checks. */
     332    uint32_t magic;
     333    /** Seamless service object. */
    324334    SeamlessMain mSeamless;
     335    /** Are we initialised yet? */
    325336    bool mIsInitialised;
    326 public:
    327     virtual const char *getPidFilePath()
    328     {
    329         return ".vboxclient-seamless.pid";
    330     }
    331     virtual int init()
    332     {
    333         int rc;
    334 
    335         if (mIsInitialised)
    336             return VERR_INTERNAL_ERROR;
    337         rc = mSeamless.init();
    338         if (RT_FAILURE(rc))
    339             return rc;
    340         rc = mSeamless.selfTest();
    341         if (RT_FAILURE(rc))
    342         {
    343             mSeamless.stop();
    344             return rc;
    345         }
    346         mIsInitialised = true;
    347         return VINF_SUCCESS;
    348     }
    349     virtual int run(bool fDaemonised /* = false */)
    350     {
    351         int rc;
    352         if (!mIsInitialised)
    353             return VERR_INTERNAL_ERROR;
    354         /* This only exits on error. */
    355         rc = mSeamless.run();
    356         mIsInitialised = false;
     337};
     338
     339static const char *getPidFilePath(void)
     340{
     341    return ".vboxclient-seamless.pid";
     342}
     343
     344static struct SEAMLESSSERVICE *getClassFromInterface(struct VBCLSERVICE **
     345                                                         ppInterface)
     346{
     347    struct SEAMLESSSERVICE *pSelf = (struct SEAMLESSSERVICE *)ppInterface;
     348    if (pSelf->magic != SEAMLESSSERVICE_MAGIC)
     349        VBClFatalError(("Bad seamless service object!\n"));
     350    return pSelf;
     351}
     352
     353static int init(struct VBCLSERVICE **ppInterface)
     354{
     355    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
     356    int rc;
     357
     358    if (pSelf->mIsInitialised)
     359        return VERR_INTERNAL_ERROR;
     360    rc = pSelf->mSeamless.init();
     361    if (RT_FAILURE(rc))
    357362        return rc;
    358     }
    359     virtual int pause() { return mSeamless.pause(); }
    360     virtual int resume() { return mSeamless.resume(); }
    361     virtual void cleanup()
    362     {
    363         VbglR3SeamlessSetCap(false);
    364     }
     363    rc = pSelf->mSeamless.selfTest();
     364    if (RT_FAILURE(rc))
     365    {
     366        pSelf->mSeamless.stop();
     367        return rc;
     368    }
     369    pSelf->mIsInitialised = true;
     370    return VINF_SUCCESS;
     371}
     372
     373static int run(struct VBCLSERVICE **ppInterface, bool fDaemonised)
     374{
     375    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
     376    int rc;
     377
     378    if (!pSelf->mIsInitialised)
     379        return VERR_INTERNAL_ERROR;
     380    /* This only exits on error. */
     381    rc = pSelf->mSeamless.run();
     382    pSelf->mIsInitialised = false;
     383    return rc;
     384}
     385
     386static int pause(struct VBCLSERVICE **ppInterface)
     387{
     388    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
     389
     390    return pSelf->mSeamless.pause();
     391}
     392
     393static int resume(struct VBCLSERVICE **ppInterface)
     394{
     395    struct SEAMLESSSERVICE *pSelf = getClassFromInterface(ppInterface);
     396
     397    return pSelf->mSeamless.resume();
     398}
     399
     400static void cleanup(struct VBCLSERVICE **ppInterface)
     401{
     402    NOREF(ppInterface);
     403    VbglR3SeamlessSetCap(false);
     404}
     405
     406struct VBCLSERVICE vbclSeamlessInterface =
     407{
     408    getPidFilePath,
     409    init,
     410    run,
     411    pause,
     412    resume,
     413    cleanup   
    365414};
    366415
    367 VBoxClient::Service *VBoxClient::GetSeamlessService()
    368 {
    369     return new SeamlessService;
    370 }
     416struct VBCLSERVICE **VBClGetSeamlessService()
     417{
     418    struct SEAMLESSSERVICE *pService =
     419        (struct SEAMLESSSERVICE *)RTMemAlloc(sizeof(*pService));
     420
     421    if (!pService)
     422        VBClFatalError(("Out of memory\n"));
     423    pService->pInterface = &vbclSeamlessInterface;
     424    pService->magic = SEAMLESSSERVICE_MAGIC;
     425    new(&pService->mSeamless) SeamlessMain();
     426    pService->mIsInitialised = false;
     427    return &pService->pInterface;
     428}
  • trunk/src/VBox/Additions/x11/VBoxClient/testcase/tstSeamlessX11.cpp

    r50495 r52562  
    2525
    2626static RTSEMEVENT eventSem;
     27
     28/** Exit with a fatal error. */
     29void vbclFatalError(char *pszMessage)
     30{
     31    RTPrintf("Fatal error: %s", pszMessage);
     32    exit(1);
     33}
    2734
    2835int VbglR3SeamlessSendRects(uint32_t cRects, PRTRECT pRects)
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette