VirtualBox

Changeset 2386 in vbox for trunk


Ignore:
Timestamp:
Apr 27, 2007 9:59:46 AM (18 years ago)
Author:
vboxsync
Message:

Clipboard RDP channel

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/hgcmsvc.h

    r1711 r2386  
    4646 * 2.1->2.2 Because pfnSaveState and pfnLoadState were added
    4747 * 2.2->3.1 Because pfnHostCall is now synchronous, returns rc, and parameters were changed
     48 * 3.1->3.2 Because pfnRegisterExtension was added
    4849 */
    49 #define VBOX_HGCM_SVC_VERSION_MINOR (0x0001)
    5050#define VBOX_HGCM_SVC_VERSION_MAJOR (0x0003)
     51#define VBOX_HGCM_SVC_VERSION_MINOR (0x0002)
    5152#define VBOX_HGCM_SVC_VERSION ((VBOX_HGCM_SVC_VERSION_MAJOR << 16) + VBOX_HGCM_SVC_VERSION_MINOR)
    5253
     
    9293typedef VBOXHGCMSVCPARM *PVBOXHGCMSVCPARM;
    9394
     95/** Service specific extension callback.
     96 *  This callback is called by the service to perform service specific operation.
     97 * 
     98 * @param pvExtension The extension pointer.
     99 * @param u32Function What the callback is supposed to do.
     100 * @param pvParm      The function parameters.
     101 * @param cbParm      The size of the function parameters.
     102 */
     103typedef DECLCALLBACK(int) FNHGCMSVCEXT(void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms);
     104typedef FNHGCMSVCEXT *PFNHGCMSVCEXT;
     105
    94106/** The Service DLL entry points.
    95107 *
     
    118130    uint32_t                 cbClient;
    119131#if ARCH_BITS == 64
    120     /** Ensure that the following pointers are properly aligned on 64-bit system.
    121      * To counter harm done by the paranoid #pragma pack(1). */
    122     uint32_t                u32Alignment0;
     132    /** Ensure that the following pointers are properly aligned on 64-bit system. */
     133    uint32_t                 u32Alignment0;
    123134#endif
    124135
     
    148159    DECLCALLBACKMEMBER(int, pfnLoadState) (uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM);
    149160
     161    /** Manage the service extension. */
     162    DECLCALLBACKMEMBER(int, pfnRegisterExtension) (PFNHGCMSVCEXT pfnExtension, void *pvExtension);
     163
    150164} VBOXHGCMSVCFNTABLE;
    151165#pragma pack()
  • trunk/include/VBox/vrdpapi.h

    r517 r2386  
    542542
    543543
    544 #define VRDP_CLIPBOARD_FORMAT_INVALID      (0xFFFFFFFF)
    545 #define VRDP_CLIPBOARD_FORMAT_UNICODE_TEXT (0)
    546 #define VRDP_CLIPBOARD_FORMAT_BITMAP       (1)
    547 
    548 VRDPR3DECL(void) VRDPSendClipboardData (HVRDPSERVER hserver, uint32_t u32Format, void *pvData, uint32_t cbData);
     544#define VRDP_CLIPBOARD_FORMAT_NULL         (0x0)
     545#define VRDP_CLIPBOARD_FORMAT_UNICODE_TEXT (0x1)
     546#define VRDP_CLIPBOARD_FORMAT_BITMAP       (0x2)
     547
     548#define VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE (0)
     549#define VRDP_CLIPBOARD_FUNCTION_DATA_READ       (1)
     550#define VRDP_CLIPBOARD_FUNCTION_DATA_WRITE      (2)
     551
     552/**
     553 * Called by the host when (VRDP_CLIPBOARD_FUNCTION_*):
     554 *   - (0) guest announces available clipboard formats;
     555 *   - (1) guest requests clipboard data;
     556 *   - (2) host responds to the client's request for clipboard data.
     557 *
     558 * @param hserver     The VRDP server handle.
     559 * @param u32Function The cause of the call.
     560 * @param u32Format   Bitmask of announced formats or the format of data.
     561 * @param pvData      Points to data from the host, as reply to (2).
     562 * @param cbData      Size of the data in bytes.
     563 *
     564 */
     565VRDPR3DECL(void) VRDPClipboard (HVRDPSERVER hserver,
     566                                uint32_t u32Function,
     567                                uint32_t u32Format,
     568                                const void *pvData,
     569                                uint32_t cbData);
    549570
    550571#ifdef VRDP_MC
     
    586607
    587608/**
    588  * Called by the server when a clipboard data is received from a client.
     609 * Called by the server when (VRDP_CLIPBOARD_FUNCTION_*):
     610 *   - (0) client announces available clipboard formats;
     611 *   - (1) client requests clipboard data;
     612 *   - (2) client responds to the guest's request for clipboard data.
     613 *
     614 *   - client announces available clipboard formats;
     615 *   - clipboard data is received from the client.
    589616 *
    590617 * @param pvCallback  Callback specific value returned by VRDPSERVERCALLBACK::pfnInterceptClipboard.
    591  * @param u32ClientId Identifies the client that sent the reply.
    592  * @param u32Format   The format of data.
     618 * @param u32ClientId Identifies the RDP client that sent the reply.
     619 * @param u32Function The cause if the callback.
     620 * @param u32Format   Bitmask of reported formats or the format of received data.
    593621 * @param pvData      Points to data received from the client.
    594622 * @param cbData      Size of the data in bytes.
     
    598626typedef DECLCALLBACK(int) FNVRDPCLIPBOARDCALLBACK (void *pvCallback,
    599627                                                   uint32_t u32ClientId,
     628                                                   uint32_t u32Function,
    600629                                                   uint32_t u32Format,
    601630                                                   const void *pvData,
  • trunk/src/VBox/Additions/WINNT/VBoxService/VBoxClipboard.cpp

    r1305 r2386  
    2424// #include <iprt/crc64.h>
    2525
    26 #define LOG_ENABLED
     26// #define LOG_ENABLED
    2727
    2828#ifdef LOG_ENABLED
     
    320320        while ((format = EnumClipboardFormats (format)) != 0)
    321321        {
     322            dprintf (("vboxClipboardChanged: format 0x%08X\n", format));
    322323            switch (format)
    323324            {
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r2382 r2386  
    666666        console->mConsoleVRDPServer->USBBackendDelete (u32ClientId);
    667667    }
     668
     669    if (fu32Intercepted & VRDP_CLIENT_INTERCEPT_CLIPBOARD)
     670    {
     671        console->mConsoleVRDPServer->ClipboardDelete (u32ClientId);
     672    }
    668673#else
    669674    console->mConsoleVRDPServer->DeleteUSBBackend ();
     
    788793}
    789794
     795#ifdef VRDP_MC
     796DECLCALLBACK(void) Console::vrdp_InterceptClipboard (void *pvUser,
     797                                                     uint32_t u32ClientId,
     798                                                     PFNVRDPCLIPBOARDCALLBACK *ppfn,
     799                                                     void **ppv)
     800{
     801    LogFlowFuncEnter();
     802
     803    Console *console = static_cast <Console *> (pvUser);
     804    AssertReturnVoid (console);
     805
     806    AutoCaller autoCaller (console);
     807    AssertComRCReturnVoid (autoCaller.rc());
     808
     809    AssertReturnVoid (console->mConsoleVRDPServer);
     810
     811    console->mConsoleVRDPServer->ClipboardCreate (u32ClientId, ppfn, ppv);
     812
     813    LogFlowFuncLeave();
     814    return;
     815}
     816#else
     817DECLCALLBACK(void) Console::vrdp_InterceptClipboard (void *pvUser,
     818                                                     PFNVRDPCLIPBOARDCALLBACK *ppfn,
     819                                                     void **ppv)
     820{
     821    /* Obsolete. */
     822    return;
     823}
     824#endif /* VRDP_MC */
     825
     826
    790827// static
    791828VRDPSERVERCALLBACK Console::sVrdpServerCallback =
     
    795832    vrdp_ClientDisconnect,
    796833    vrdp_InterceptAudio,
    797     vrdp_InterceptUSB
     834    vrdp_InterceptUSB,
     835    vrdp_InterceptClipboard
    798836};
    799837
  • trunk/src/VBox/Main/ConsoleVRDPServer.cpp

    r2333 r2386  
    2626#include "Logging.h"
    2727
     28#include <iprt/asm.h>
    2829#include <iprt/ldr.h>
    2930
     
    3334// ConsoleVRDPServer
    3435////////////////////////////////////////////////////////////////////////////////
     36
     37#define VBOX_CLIPBOARD_NO_DATA      0
     38#define VBOX_CLIPBOARD_DATA_WAITING 1
     39#define VBOX_CLIPBOARD_DATA_ARRIVED 2
    3540
    3641#ifdef VBOX_VRDP
     
    5156void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, void *pvUpdate, uint32_t cbUpdate);
    5257void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPQueryInfo)       (HVRDPSERVER hserver, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
     58void (VBOXCALL *ConsoleVRDPServer::mpfnVRDPClipboard)       (HVRDPSERVER hserver, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData);
    5359#endif
    5460
     
    6066    int rc = RTCritSectInit (&mCritSect);
    6167    AssertRC (rc);
    62 
     68   
     69    mcClipboardRefs = 0;
     70    mpfnClipboardCallback = NULL;
     71
     72    rc = RTSemEventMultiCreate(&mEventClipboardData);
     73    AssertRC (rc);
     74    mpvClipboardData = NULL;
     75    mcbClipboardData = 0;
     76    mfu32ClipboardWaitData = VBOX_CLIPBOARD_NO_DATA;
     77   
    6378#ifdef VBOX_WITH_USB
    6479    mUSBBackends.pHead = NULL;
     
    86101#ifdef VRDP_MC
    87102    Stop ();
     103   
     104    RTSemEventMultiDestroy (mEventClipboardData);
    88105
    89106    if (RTCritSectIsInitialized (&mCritSect))
     
    417434}
    418435
     436DECLCALLBACK(int) ConsoleVRDPServer::ClipboardCallback (void *pvCallback,
     437                                                        uint32_t u32ClientId,
     438                                                        uint32_t u32Function,
     439                                                        uint32_t u32Format,
     440                                                        const void *pvData,
     441                                                        uint32_t cbData)
     442{
     443    LogFlowFunc(("pvCallback = %p, u32ClientId = %d, u32Function = %d, u32Format = 0x%08X, pvData = %p, cbData = %d\n",
     444                 pvCallback, u32ClientId, u32Function, u32Format, pvData, cbData));
     445
     446    int rc = VINF_SUCCESS;
     447   
     448    ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvCallback);
     449   
     450    NOREF(u32ClientId);
     451   
     452    switch (u32Function)
     453    {
     454        case VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE:
     455        {
     456            if (pServer->mpfnClipboardCallback)
     457            {
     458                pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE,
     459                                                u32Format,
     460                                                (void *)pvData,
     461                                                cbData);
     462            }
     463           
     464            /* Discard current data. */
     465            ASMAtomicCmpXchgU32(&pServer->mfu32ClipboardWaitData, VBOX_CLIPBOARD_NO_DATA, VBOX_CLIPBOARD_DATA_ARRIVED);
     466        } break;
     467       
     468        case VRDP_CLIPBOARD_FUNCTION_DATA_READ:
     469        {
     470            if (pServer->mpfnClipboardCallback)
     471            {
     472                pServer->mpfnClipboardCallback (VBOX_CLIPBOARD_EXT_FN_DATA_READ,
     473                                                u32Format,
     474                                                (void *)pvData,
     475                                                cbData);
     476            }
     477        } break;
     478
     479        case VRDP_CLIPBOARD_FUNCTION_DATA_WRITE:
     480        {
     481            if (ASMAtomicCmpXchgU32(&pServer->mfu32ClipboardWaitData, VBOX_CLIPBOARD_DATA_ARRIVED, VBOX_CLIPBOARD_DATA_WAITING))
     482            {
     483                LogFlowFunc(("Got clipboard data\n"));
     484               
     485                if (pServer->mpvClipboardData)
     486                {
     487                    RTMemFree (pServer->mpvClipboardData);
     488                    pServer->mpvClipboardData = NULL;
     489                }
     490               
     491                if (cbData)
     492                {
     493                    void *pv = RTMemAlloc (cbData);
     494           
     495                    memcpy (pv, pvData, cbData);
     496           
     497                    pServer->mpvClipboardData = pv;
     498                    pServer->mcbClipboardData = cbData;
     499                }
     500                else
     501                {
     502                    pServer->mpvClipboardData = NULL;
     503                    pServer->mcbClipboardData = 0;
     504                }
     505           
     506                RTSemEventMultiSignal (pServer->mEventClipboardData);
     507            }
     508        } break;
     509
     510        default:
     511            rc = VERR_NOT_SUPPORTED;
     512    }
     513   
     514    return rc;
     515}
     516
     517DECLCALLBACK(int) ConsoleVRDPServer::ClipboardServiceExtension (void *pvExtension,
     518                                                                uint32_t u32Function,
     519                                                                void *pvParms,
     520                                                                uint32_t cbParms)
     521{
     522    LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
     523                 pvExtension, u32Function, pvParms, cbParms));
     524   
     525    int rc = VINF_SUCCESS;
     526   
     527    ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvExtension);
     528   
     529    VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
     530   
     531    switch (u32Function)
     532    {
     533        case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
     534        {
     535            pServer->mpfnClipboardCallback = (PFNVRDPCLIPBOARDEXTCALLBACK)pParms->pvData;
     536        } break;
     537
     538        case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
     539        {
     540            if (mpfnVRDPClipboard)
     541            {
     542                mpfnVRDPClipboard (pServer->mhServer,
     543                                   VRDP_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE,
     544                                   pParms->u32Format,
     545                                   NULL,
     546                                   0);
     547            }
     548        } break;
     549
     550        case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
     551        {
     552            if (mpfnVRDPClipboard)
     553            {
     554                if (ASMAtomicCmpXchgU32(&pServer->mfu32ClipboardWaitData, VBOX_CLIPBOARD_DATA_WAITING, VBOX_CLIPBOARD_NO_DATA))
     555                {
     556                    LogFlowFunc(("Wait for clipboard data\n"));
     557                    RTSemEventMultiReset(pServer->mEventClipboardData);
     558                   
     559                    mpfnVRDPClipboard (pServer->mhServer,
     560                                       VRDP_CLIPBOARD_FUNCTION_DATA_READ,
     561                                       pParms->u32Format,
     562                                       NULL,
     563                                       0);
     564                   
     565                    /* Wait for the client. 10 seconds should be enough. */
     566                    int rc = RTSemEventMultiWait(pServer->mEventClipboardData, 10*1000);
     567                    LogFlowFunc (("Wait completed rc = %d.\n", rc)); NOREF(rc);
     568                }
     569               
     570                if (pServer->mfu32ClipboardWaitData == VBOX_CLIPBOARD_DATA_ARRIVED)
     571                {
     572                    LogFlowFunc(("Return clipboard data: pParms->cbData = %d, mcbClipboardData = %d\n", pParms->cbData, pServer->mcbClipboardData));
     573                    if (pParms->cbData >= pServer->mcbClipboardData)
     574                    {
     575                        if (pServer->mcbClipboardData)
     576                        {
     577                            memcpy (pParms->pvData, pServer->mpvClipboardData, pServer->mcbClipboardData);
     578                        }
     579                   
     580                        RTMemFree (pServer->mpvClipboardData);
     581                        pServer->mpvClipboardData = NULL;
     582                       
     583                        pServer->mfu32ClipboardWaitData = VBOX_CLIPBOARD_NO_DATA;
     584                    }
     585               
     586                    pParms->cbData = pServer->mcbClipboardData;
     587                }
     588                else
     589                {
     590                    pParms->pvData = NULL;
     591                    pParms->cbData = 0;
     592                }
     593            }
     594        } break;
     595
     596        case VBOX_CLIPBOARD_EXT_FN_DATA_WRITE:
     597        {
     598            if (mpfnVRDPClipboard)
     599            {
     600                mpfnVRDPClipboard (pServer->mhServer,
     601                                   VRDP_CLIPBOARD_FUNCTION_DATA_WRITE,
     602                                   pParms->u32Format,
     603                                   pParms->pvData,
     604                                   pParms->cbData);
     605            }
     606        } break;
     607       
     608        default:
     609            rc = VERR_NOT_SUPPORTED;
     610    }
     611   
     612    return rc;
     613}
     614
     615void ConsoleVRDPServer::ClipboardCreate (uint32_t u32ClientId, PFNVRDPCLIPBOARDCALLBACK *ppfn, void **ppv)
     616{
     617    int rc = lockConsoleVRDPServer ();
     618       
     619    if (VBOX_SUCCESS (rc))
     620    {
     621        if (mcClipboardRefs == 0)
     622        {
     623            rc = HGCMHostRegisterServiceExtension (&mhClipboard, "VBoxSharedClipboard", ClipboardServiceExtension, this);
     624           
     625            if (VBOX_SUCCESS (rc))
     626            {
     627                mcClipboardRefs++;
     628            }
     629        }
     630       
     631        if (VBOX_SUCCESS (rc))
     632        {
     633            *ppfn = ClipboardCallback;
     634            *ppv = this;
     635        }
     636
     637        unlockConsoleVRDPServer ();
     638    }
     639}
     640
     641void ConsoleVRDPServer::ClipboardDelete (uint32_t u32ClientId)
     642{
     643    int rc = lockConsoleVRDPServer ();
     644       
     645    if (VBOX_SUCCESS (rc))
     646    {
     647        mcClipboardRefs--;
     648       
     649        if (mcClipboardRefs == 0)
     650        {
     651            HGCMHostUnregisterServiceExtension (mhClipboard);
     652        }
     653
     654        unlockConsoleVRDPServer ();
     655    }
     656}
     657
    419658/* That is called on INPUT thread of the VRDP server.
    420659 * The ConsoleVRDPServer keeps a list of created backend instances.
     
    8251064                DEFSYMENTRY(VRDPSendUSBRequest),
    8261065                DEFSYMENTRY(VRDPQueryInfo),
     1066                DEFSYMENTRY(VRDPClipboard)
    8271067            };
    8281068
  • trunk/src/VBox/Main/hgcm/HGCM.cpp

    r2072 r2386  
    6666#define VBOX_HGCM_SVC_NAME_MAX_BYTES 1024
    6767
     68struct _HGCMSVCEXTHANDLEDATA
     69{
     70    char *pszServiceName;
     71    /* The service name follows. */
     72};
     73
    6874/** Internal helper service object. HGCM code would use it to
    6975 *  hold information about services and communicate with services.
     
    103109
    104110        uint32_t *m_paClientIds;
     111       
     112        HGCMSVCEXTHANDLE m_hExtension;
    105113
    106114        int loadServiceDLL (void);
     
    127135         */
    128136        static int LoadService (const char *pszServiceLibrary, const char *pszServiceName);
    129         void UnloadService ();
     137        void UnloadService (void);
    130138
    131139        static void UnloadAll (void);
     
    146154
    147155        uint32_t SizeOfClient (void) { return m_fntable.cbClient; };
     156
     157        int RegisterExtension (HGCMSVCEXTHANDLE handle, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
     158        void UnregisterExtension (HGCMSVCEXTHANDLE handle);
    148159
    149160        /*
     
    213224    m_cClients   (0),
    214225    m_cClientsAllocated (0),
    215     m_paClientIds (NULL)
     226    m_paClientIds (NULL),
     227    m_hExtension (NULL)
    216228{
    217229    memset (&m_fntable, 0, sizeof (m_fntable));
     
    230242int HGCMService::loadServiceDLL (void)
    231243{
    232     LogFlow(("HGCMService::loadServiceDLL: m_pszSvcLibrary = %s\n", m_pszSvcLibrary));
     244    LogFlowFunc(("m_pszSvcLibrary = %s\n", m_pszSvcLibrary));
    233245
    234246    if (m_pszSvcLibrary == NULL)
     
    243255    if (VBOX_SUCCESS(rc))
    244256    {
    245         LogFlow(("HGCMService::loadServiceDLL: successfully loaded the library.\n"));
     257        LogFlowFunc(("successfully loaded the library.\n"));
    246258
    247259        m_pfnLoad = NULL;
     
    270282            rc = m_pfnLoad (&m_fntable);
    271283
    272             LogFlow(("HGCMService::loadServiceDLL: m_pfnLoad rc = %Vrc\n", rc));
     284            LogFlowFunc(("m_pfnLoad rc = %Vrc\n", rc));
    273285
    274286            if (VBOX_SUCCESS (rc))
     
    294306    else
    295307    {
    296         LogFlow(("HGCMService::loadServiceDLL: failed to load service library. The service is not available %Vrc\n", rc));
     308        LogFlowFunc(("failed to load service library. The service is not available %Vrc\n", rc));
    297309        m_hLdrMod = NIL_RTLDRMOD;
    298310    }
     
    335347#define SVC_MSG_SAVESTATE  (7)  /* pfnSaveState. */
    336348#define SVC_MSG_QUIT       (8)  /* Terminate the thread. */
     349#define SVC_MSG_REGEXT     (9)  /* pfnRegisterExtension */
     350#define SVC_MSG_UNREGEXT   (10) /* pfnRegisterExtension */
    337351
    338352class HGCMMsgSvcLoad: public HGCMMsgCore
     
    403417
    404418        VBOXHGCMSVCPARM *paParms;
     419};
     420
     421class HGCMMsgSvcRegisterExtension: public HGCMMsgCore
     422{
     423    public:
     424        /* Handle of the extension to be registered. */
     425        HGCMSVCEXTHANDLE handle;
     426        /* The extension entry point. */
     427        PFNHGCMSVCEXT pfnExtension;
     428        /* The extension pointer. */
     429        void *pvExtension;
     430};
     431
     432class HGCMMsgSvcUnregisterExtension: public HGCMMsgCore
     433{
     434    public:
     435        /* Handle of the registered extension. */
     436        HGCMSVCEXTHANDLE handle;
    405437};
    406438
     
    417449        case SVC_MSG_LOADSTATE:     
    418450        case SVC_MSG_SAVESTATE:   return new HGCMMsgLoadSaveStateClient ();
     451        case SVC_MSG_REGEXT:      return new HGCMMsgSvcRegisterExtension ();
     452        case SVC_MSG_UNREGEXT:    return new HGCMMsgSvcUnregisterExtension ();
    419453        default:
    420454            AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
     
    581615                {
    582616                    rc = VERR_HGCM_INVALID_CLIENT_ID;
     617                }
     618            } break;
     619           
     620            case SVC_MSG_REGEXT:
     621            {
     622                HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)pMsgCore;
     623
     624                LogFlowFunc(("SVC_MSG_REGEXT handle = %p, pfn = %p\n", pMsg->handle, pMsg->pfnExtension));
     625               
     626                if (pSvc->m_hExtension)
     627                {
     628                    rc = VERR_NOT_SUPPORTED;
     629                }
     630                else
     631                {
     632                    if (pSvc->m_fntable.pfnRegisterExtension)
     633                    {
     634                        rc = pSvc->m_fntable.pfnRegisterExtension (pMsg->pfnExtension, pMsg->pvExtension);
     635                    }
     636                    else
     637                    {
     638                        rc = VERR_NOT_SUPPORTED;
     639                    }
     640                   
     641                    if (VBOX_SUCCESS (rc))
     642                    {
     643                        pSvc->m_hExtension = pMsg->handle;
     644                    }
     645                }
     646            } break;
     647
     648            case SVC_MSG_UNREGEXT:
     649            {
     650                HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)pMsgCore;
     651
     652                LogFlowFunc(("SVC_MSG_UNREGEXT handle = %p\n", pMsg->handle));
     653               
     654                if (pSvc->m_hExtension != pMsg->handle)
     655                {
     656                    rc = VERR_NOT_SUPPORTED;
     657                }
     658                else
     659                {
     660                    if (pSvc->m_fntable.pfnRegisterExtension)
     661                    {
     662                        rc = pSvc->m_fntable.pfnRegisterExtension (NULL, NULL);
     663                    }
     664                    else
     665                    {
     666                        rc = VERR_NOT_SUPPORTED;
     667                    }
     668                   
     669                    pSvc->m_hExtension = NULL;
    583670                }
    584671            } break;
     
    12781365}
    12791366
    1280 /* Perform a host call the service.
     1367int HGCMService::RegisterExtension (HGCMSVCEXTHANDLE handle,
     1368                                    PFNHGCMSVCEXT pfnExtension,
     1369                                    void *pvExtension)
     1370{
     1371    LogFlowFunc(("%s\n", handle->pszServiceName));
     1372
     1373    /* Forward the message to the service thread. */
     1374    HGCMMSGHANDLE hMsg = 0;
     1375    int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_REGEXT, hgcmMessageAllocSvc);
     1376
     1377    if (VBOX_SUCCESS(rc))
     1378    {
     1379        HGCMMsgSvcRegisterExtension *pMsg = (HGCMMsgSvcRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
     1380        AssertRelease(pMsg);
     1381
     1382        pMsg->handle       = handle;
     1383        pMsg->pfnExtension = pfnExtension;
     1384        pMsg->pvExtension  = pvExtension;
     1385
     1386        hgcmObjDereference (pMsg);
     1387
     1388        rc = hgcmMsgSend (hMsg);
     1389    }
     1390
     1391    LogFlowFunc(("rc = %Vrc\n", rc));
     1392    return rc;
     1393}
     1394
     1395void HGCMService::UnregisterExtension (HGCMSVCEXTHANDLE handle)
     1396{
     1397    /* Forward the message to the service thread. */
     1398    HGCMMSGHANDLE hMsg = 0;
     1399    int rc = hgcmMsgAlloc (m_thread, &hMsg, SVC_MSG_UNREGEXT, hgcmMessageAllocSvc);
     1400
     1401    if (VBOX_SUCCESS(rc))
     1402    {
     1403        HGCMMsgSvcUnregisterExtension *pMsg = (HGCMMsgSvcUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
     1404        AssertRelease(pMsg);
     1405
     1406        pMsg->handle = handle;
     1407
     1408        hgcmObjDereference (pMsg);
     1409
     1410        rc = hgcmMsgSend (hMsg);
     1411    }
     1412
     1413    LogFlowFunc(("rc = %Vrc\n", rc));
     1414}
     1415
     1416/* Perform a guest call to the service.
    12811417 *
    12821418 * @param pHGCMPort      The port to be used for completion confirmation.
     
    13191455    }
    13201456
     1457    LogFlowFunc(("rc = %Vrc\n", rc));
    13211458    return rc;
    13221459}
     
    13691506#define HGCM_MSG_RESET      (16)  /* Disconnect all clients from the specified service. */
    13701507#define HGCM_MSG_QUIT       (17)  /* Unload all services and terminate the thread. */
     1508#define HGCM_MSG_REGEXT     (18)  /* Register a service extension. */
     1509#define HGCM_MSG_UNREGEXT   (19)  /* Unregister a service extension. */
    13711510
    13721511class HGCMMsgMainConnect: public HGCMMsgHeader
     
    14231562};
    14241563
     1564class HGCMMsgMainRegisterExtension: public HGCMMsgCore
     1565{
     1566    public:
     1567        /* Returned handle to be used in HGCMMsgMainUnregisterExtension. */
     1568        HGCMSVCEXTHANDLE *pHandle;
     1569        /* Name of the service. */
     1570        const char *pszServiceName;
     1571        /* The extension entry point. */
     1572        PFNHGCMSVCEXT pfnExtension;
     1573        /* The extension pointer. */
     1574        void *pvExtension;
     1575};
     1576
     1577class HGCMMsgMainUnregisterExtension: public HGCMMsgCore
     1578{
     1579    public:
     1580        /* Handle of the registered extension. */
     1581        HGCMSVCEXTHANDLE handle;
     1582};
     1583
    14251584static HGCMMsgCore *hgcmMainMessageAlloc (uint32_t u32MsgId)
    14261585{
     
    14351594        case HGCM_MSG_RESET:      return new HGCMMsgMainReset ();
    14361595        case HGCM_MSG_QUIT:       return new HGCMMsgMainQuit ();
     1596        case HGCM_MSG_REGEXT:     return new HGCMMsgMainRegisterExtension ();
     1597        case HGCM_MSG_UNREGEXT:   return new HGCMMsgMainUnregisterExtension ();
    14371598        default:
    14381599            AssertReleaseMsgFailed(("Msg id = %08X\n", u32MsgId));
     
    15781739            } break;
    15791740
     1741            case HGCM_MSG_REGEXT:
     1742            {
     1743                HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)pMsgCore;
     1744               
     1745                LogFlowFunc(("HGCM_MSG_REGEXT\n"));
     1746               
     1747                /* Allocate the handle data. */
     1748                HGCMSVCEXTHANDLE handle = (HGCMSVCEXTHANDLE)RTMemAllocZ (sizeof (struct _HGCMSVCEXTHANDLEDATA)
     1749                                                                         + strlen (pMsg->pszServiceName)
     1750                                                                         + sizeof (char));
     1751               
     1752                if (handle == NULL)
     1753                {
     1754                    rc = VERR_NO_MEMORY;
     1755                }
     1756                else
     1757                {
     1758                    handle->pszServiceName = (char *)((uint8_t *)handle + sizeof (struct _HGCMSVCEXTHANDLEDATA));
     1759                    strcpy (handle->pszServiceName, pMsg->pszServiceName);
     1760                   
     1761                    HGCMService *pService;
     1762                    rc = HGCMService::ResolveService (&pService, handle->pszServiceName);
     1763
     1764                    if (VBOX_SUCCESS (rc))
     1765                    {
     1766                        pService->RegisterExtension (handle, pMsg->pfnExtension, pMsg->pvExtension);
     1767
     1768                        pService->ReleaseService ();
     1769                    }
     1770                   
     1771                    if (VBOX_FAILURE (rc))
     1772                    {
     1773                        RTMemFree (handle);
     1774                    }
     1775                    else
     1776                    {
     1777                        *pMsg->pHandle = handle;
     1778                    }
     1779                }
     1780            } break;
     1781
     1782            case HGCM_MSG_UNREGEXT:
     1783            {
     1784                HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)pMsgCore;
     1785
     1786                LogFlowFunc(("HGCM_MSG_UNREGEXT\n"));
     1787
     1788                HGCMService *pService;
     1789                rc = HGCMService::ResolveService (&pService, pMsg->handle->pszServiceName);
     1790
     1791                if (VBOX_SUCCESS (rc))
     1792                {
     1793                    pService->UnregisterExtension (pMsg->handle);
     1794
     1795                    pService->ReleaseService ();
     1796                }
     1797               
     1798                RTMemFree (pMsg->handle);
     1799            } break;
     1800
    15801801            default:
    15811802            {
     
    16471868}
    16481869
     1870/* Register a HGCM service extension.
     1871 *
     1872 * @param pHandle            Returned handle for the registered extension.
     1873 * @param pszServiceName     The name of the service.
     1874 * @param pfnExtension       The extension callback.
     1875 * @return VBox rc.
     1876 */
     1877int HGCMHostRegisterServiceExtension (HGCMSVCEXTHANDLE *pHandle,
     1878                                      const char *pszServiceName,
     1879                                      PFNHGCMSVCEXT pfnExtension,
     1880                                      void *pvExtension)
     1881{
     1882    LogFlowFunc(("pHandle = %p, name = %s, pfn = %p, rv = %p\n", pHandle, pszServiceName, pfnExtension, pvExtension));
     1883
     1884    if (!pHandle || !pszServiceName || !pfnExtension)
     1885    {
     1886        return VERR_INVALID_PARAMETER;
     1887    }
     1888
     1889    /* Forward the request to the main hgcm thread. */
     1890    HGCMMSGHANDLE hMsg = 0;
     1891
     1892    int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_REGEXT, hgcmMainMessageAlloc);
     1893
     1894    if (VBOX_SUCCESS(rc))
     1895    {
     1896        /* Initialize the message. Since the message is synchronous, use the supplied pointers. */
     1897        HGCMMsgMainRegisterExtension *pMsg = (HGCMMsgMainRegisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
     1898        AssertRelease(pMsg);
     1899
     1900        pMsg->pHandle        = pHandle;
     1901        pMsg->pszServiceName = pszServiceName;
     1902        pMsg->pfnExtension   = pfnExtension;
     1903        pMsg->pvExtension    = pvExtension;
     1904
     1905        hgcmObjDereference (pMsg);
     1906
     1907        rc = hgcmMsgSend (hMsg);
     1908    }
     1909
     1910    LogFlowFunc(("*pHandle = %p, rc = %Vrc\n", *pHandle, rc));
     1911    return rc;
     1912}
     1913
     1914void HGCMHostUnregisterServiceExtension (HGCMSVCEXTHANDLE handle)
     1915{
     1916    LogFlowFunc(("handle = %p\n", handle));
     1917
     1918    /* Forward the request to the main hgcm thread. */
     1919    HGCMMSGHANDLE hMsg = 0;
     1920
     1921    int rc = hgcmMsgAlloc (g_hgcmThread, &hMsg, HGCM_MSG_UNREGEXT, hgcmMainMessageAlloc);
     1922
     1923    if (VBOX_SUCCESS(rc))
     1924    {
     1925        /* Initialize the message. */
     1926        HGCMMsgMainUnregisterExtension *pMsg = (HGCMMsgMainUnregisterExtension *)hgcmObjReference (hMsg, HGCMOBJ_MSG);
     1927        AssertRelease(pMsg);
     1928
     1929        pMsg->handle = handle;
     1930
     1931        hgcmObjDereference (pMsg);
     1932
     1933        rc = hgcmMsgSend (hMsg);
     1934    }
     1935
     1936    LogFlowFunc(("rc = %Vrc\n", rc));
     1937    return;
     1938}
    16491939
    16501940/* Find a service and inform it about a client connection, create a client handle.
  • trunk/src/VBox/Main/hgcm/HGCMThread.cpp

    r1788 r2386  
    200200    pThread->m_fu32ThreadFlags |= HGCMMSG_TF_TERMINATED;
    201201
     202    pThread->m_thread = NIL_RTTHREAD;
     203
    202204    hgcmObjDeleteHandle (pThread->Handle ());
    203 
    204     pThread->m_thread = NIL_RTTHREAD;
    205205
    206206    LogFlow(("MAIN::hgcmWorkerThreadFunc: completed HGCM thread %p\n", pThread));
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r2382 r2386  
    410410    static DECLCALLBACK(void)   vrdp_InterceptAudio (void *pvUser, uint32_t u32ClientId);
    411411    static DECLCALLBACK(void)   vrdp_InterceptUSB (void *pvUser, uint32_t u32ClientId, PFNVRDPUSBCALLBACK *ppfn, void **ppv);
     412    static DECLCALLBACK(void)   vrdp_InterceptClipboard (void *pvUser, uint32_t u32ClientId, PFNVRDPCLIPBOARDCALLBACK *ppfn, void **ppv);
    412413#else
    413414    static DECLCALLBACK(int)    vrdp_ClientLogon (void *pvUser, const char *pszUser, const char *pszPassword, const char *pszDomain);
     
    416417    static DECLCALLBACK(void)   vrdp_InterceptAudio (void *pvUser, bool keepHostAudio);
    417418    static DECLCALLBACK(void)   vrdp_InterceptUSB (void *pvUser, PFNVRDPUSBCALLBACK *ppfn, void **ppv);
     419    static DECLCALLBACK(void)   vrdp_InterceptClipboard (void *pvUser, PFNVRDPCLIPBOARDCALLBACK *ppfn, void **ppv);
    418420#endif /* VRDP_MC */
    419421
  • trunk/src/VBox/Main/include/ConsoleVRDPServer.h

    r300 r2386  
    2424
    2525#include "RemoteUSBBackend.h"
     26#include "hgcm/hgcm.h"
    2627
    2728#include <VBox/VRDPAuth.h>
     29
     30#include <VBox/HostServices/VBoxClipboardExt.h>
    2831
    2932// ConsoleVRDPServer
     
    6164    void waitRemoteUSBThreadEvent (unsigned cMillies);
    6265   
     66    void ClipboardCreate (uint32_t u32ClientId, PFNVRDPCLIPBOARDCALLBACK *ppfn, void **ppv);
     67    void ClipboardDelete (uint32_t u32ClientId);
    6368#else
    6469    void CreateUSBBackend (PFNVRDPUSBCALLBACK *ppfn, void **ppv);
     
    116121    static void (VBOXCALL *mpfnVRDPSendUpdate)      (HVRDPSERVER hServer, void *pvUpdate, uint32_t cbUpdate);
    117122    static void (VBOXCALL *mpfnVRDPQueryInfo)       (HVRDPSERVER hserver, uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut);
     123    static void (VBOXCALL *mpfnVRDPClipboard)       (HVRDPSERVER hserver, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData);
    118124#endif
    119125
     
    123129    int lockConsoleVRDPServer (void);
    124130    void unlockConsoleVRDPServer (void);
    125 
     131   
     132    int mcClipboardRefs;
     133    HGCMSVCEXTHANDLE mhClipboard;
     134    PFNVRDPCLIPBOARDEXTCALLBACK mpfnClipboardCallback;
     135
     136    RTSEMEVENTMULTI   mEventClipboardData;
     137    void             *mpvClipboardData;
     138    uint32_t          mcbClipboardData;
     139    volatile uint32_t mfu32ClipboardWaitData;
     140
     141    static DECLCALLBACK(int) ClipboardCallback (void *pvCallback, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData);
     142    static DECLCALLBACK(int) ClipboardServiceExtension (void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms);
     143   
    126144#ifdef VBOX_WITH_USB
    127145    RemoteUSBBackend *usbBackendFindByUUID (const Guid *pGuid);
  • trunk/src/VBox/Main/include/hgcm/HGCM.h

    r1711 r2386  
    3333#define HGCM_SSM_VERSION    2
    3434
     35/* Handle of a HGCM service extension. */
     36struct _HGCMSVCEXTHANDLEDATA;
     37typedef struct _HGCMSVCEXTHANDLEDATA *HGCMSVCEXTHANDLE;
     38
    3539__BEGIN_DECLS
    3640int HGCMHostInit (void);
     
    4044
    4145int HGCMHostLoad (const char *pszServiceName, const char *pszServiceLibrary);
     46
     47int HGCMHostRegisterServiceExtension (HGCMSVCEXTHANDLE *pHandle, const char *pszServiceName, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
     48void HGCMHostUnregisterServiceExtension (HGCMSVCEXTHANDLE handle);
    4249
    4350int HGCMGuestConnect (PPDMIHGCMPORT pHGCMPort, PVBOXHGCMCMD pCmdPtr, const char *pszServiceName, uint32_t *pClientID);
Note: See TracChangeset for help on using the changeset viewer.

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