VirtualBox

Changeset 2386

Show
Ignore:
Timestamp:
04/27/07 11:59:46 (2 years ago)
Author:
vboxsync
Message:

Clipboard RDP channel

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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