VirtualBox

Changeset 75853 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 30, 2018 7:26:42 PM (6 years ago)
Author:
vboxsync
Message:

GuestControl,HGCM,VBoxService: Save/restore related optimizations and changes. bugref:9313

Location:
trunk/src/VBox
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp

    r75824 r75853  
    307307
    308308
    309 
    310309/**
    311310 * Peeks at the next host message, waiting for one to turn up.
     
    314313 * @retval  VERR_INTERRUPTED if interrupted.  Does the necessary cleanup, so
    315314 *          caller just have to repeat this call.
     315 * @retval  VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
    316316 *
    317317 * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
     
    319319 * @param   pcParameters    Where to store the number  of parameters which will
    320320 *                          be received in a second call to the host.
    321  */
    322 VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters)
     321 * @param   pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
     322 *                          for the VM restore check.  Optional.
     323 *
     324 * @note    Restore check is only performed optimally with a 6.0 host.
     325 */
     326VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck)
    323327{
    324328    AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
     
    328332    if (vbglR3GuestCtrlSupportsPeekGetCancel(idClient))
    329333    {
    330         HGCMMsgCmdWaitFor Msg;
    331         VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_PEEK_WAIT, 2);
    332         VbglHGCMParmUInt32Set(&Msg.msg, 0);
    333         VbglHGCMParmUInt32Set(&Msg.num_parms, 0);
    334         rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     334        struct
     335        {
     336            VBGLIOCHGCMCALL Hdr;
     337            HGCMFunctionParameter idMsg;       /* Doubles as restore check on input. */
     338            HGCMFunctionParameter cParameters;
     339        } Msg;
     340        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_PEEK_WAIT, 2);
     341        VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
     342        VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
     343        rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
    335344        LogRel(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc));
    336345        if (RT_SUCCESS(rc))
    337346        {
    338             AssertMsgReturn(   Msg.msg.type       == VMMDevHGCMParmType_32bit
    339                             && Msg.num_parms.type == VMMDevHGCMParmType_32bit,
    340                             ("msg.type=%d num_parms.type=%d\n", Msg.msg.type, Msg.num_parms.type),
     347            AssertMsgReturn(   Msg.idMsg.type       == VMMDevHGCMParmType_64bit
     348                            && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
     349                            ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
    341350                            VERR_INTERNAL_ERROR_3);
    342351
    343             *pidMsg       = Msg.msg.u.value32;
    344             *pcParameters = Msg.num_parms.u.value32;
     352            *pidMsg       = (uint32_t)Msg.idMsg.u.value64;
     353            *pcParameters = Msg.cParameters.u.value32;
    345354            return rc;
    346355        }
     
    351360        if (rc == VERR_INTERRUPTED)
    352361        {
    353             VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient, GUEST_MSG_CANCEL, 0);
    354             int rc2 = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg.hdr));
     362            VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, GUEST_MSG_CANCEL, 0);
     363            int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
    355364            AssertRC(rc2);
    356365        }
     366
     367        /*
     368         * If restored, update pidRestoreCheck.
     369         */
     370        if (rc == VERR_VM_RESTORED && pidRestoreCheck)
     371            *pidRestoreCheck = Msg.idMsg.u.value64;
    357372
    358373        *pidMsg       = UINT32_MAX - 1;
     
    363378    /*
    364379     * Fallback if host < v6.0.
     380     *
     381     * Note! The restore check isn't perfect. Would require checking afterwards
     382     *       and stash the result if we were restored during the call.  Too much
     383     *       hazzle for a downgrade scenario.
    365384     */
     385    if (pidRestoreCheck)
     386    {
     387        uint64_t idRestoreCur = *pidRestoreCheck;
     388        rc = VbglR3GetSessionId(&idRestoreCur);
     389        if (RT_SUCCESS(rc) && idRestoreCur != *pidRestoreCheck)
     390        {
     391            *pidRestoreCheck = idRestoreCur;
     392            return VERR_VM_RESTORED;
     393        }
     394    }
     395
    366396    rc = vbglR3GuestCtrlMsgWaitFor(idClient, pidMsg, pcParameters);
    367397    if (rc == VERR_TOO_MUCH_DATA)
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r75824 r75853  
    251251    AssertReturn(pvScratchBuf, VERR_NO_MEMORY);
    252252
    253     VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient, 0 /*idContext*/, 2 /*uProtocol*/, 0  /*cParms*/ };
    254 
    255253    int rc = VINF_SUCCESS;      /* (shut up compiler warnings) */
    256254    int cRetrievalFailed = 0;   /* Number of failed message retrievals in a row. */
     
    258256    {
    259257        VGSvcVerbose(3, "GstCtrl: Waiting for host msg ...\n");
    260         uint32_t idMsg  = 0;
    261         uint32_t cParms = 0;
    262         rc = VbglR3GuestCtrlMsgPeekWait(g_idControlSvcClient, &idMsg, &cParms);
     258        VBGLR3GUESTCTRLCMDCTX ctxHost = { g_idControlSvcClient, 0 /*idContext*/, 2 /*uProtocol*/, 0  /*cParms*/ };
     259        uint32_t              idMsg  = 0;
     260        rc = VbglR3GuestCtrlMsgPeekWait(g_idControlSvcClient, &idMsg, &ctxHost.uNumParms, &g_idControlSession);
    263261        if (RT_SUCCESS(rc))
    264262        {
    265263            cRetrievalFailed = 0; /* Reset failed retrieval count. */
    266             VGSvcVerbose(4, "idMsg=%RU32 (%s) (%RU32 parms) retrieved\n", idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms);
    267 
    268             /*
    269              * Close all open guest sessions if the VM was restored (all context IDs,
    270              * sessions, etc. are now invalid).
    271              *
    272              * Note! This will suck performance wise if we get a lot of messages thru here.
    273              *       What about the service returning a HOST_MSG_RESTORED message?
    274              */
    275             uint64_t idNewSession = g_idControlSession;
    276             int rc2 = VbglR3GetSessionId(&idNewSession);
    277             if (   RT_SUCCESS(rc2)
    278                 && idNewSession != g_idControlSession)
    279             {
    280                 VGSvcVerbose(1, "The VM session ID changed (i.e. restored).\n");
    281                 g_idControlSession = idNewSession;
    282                 rc2 = VGSvcGstCtrlSessionClose(&g_Session);
    283                 AssertRC(rc2);
    284             }
     264            VGSvcVerbose(4, "idMsg=%RU32 (%s) (%RU32 parms) retrieved\n",
     265                         idMsg, GstCtrlHostFnName((eHostFn)idMsg), ctxHost.uNumParms);
    285266
    286267            /*
    287268             * Handle the host message.
    288269             */
    289             ctxHost.uNumParms = cParms;
    290270            switch (idMsg)
    291271            {
     
    308288                        rc = VbglR3GuestCtrlMsgSkip(g_idControlSvcClient, VERR_NOT_SUPPORTED, idMsg);
    309289                        VGSvcVerbose(1, "Skipped unexpected message idMsg=%RU32 (%s), cParms=%RU32 (rc=%Rrc)\n",
    310                                      idMsg, GstCtrlHostFnName((eHostFn)idMsg), cParms, rc);
     290                                     idMsg, GstCtrlHostFnName((eHostFn)idMsg), ctxHost.uNumParms, rc);
    311291                    }
    312292                    else
    313293                    {
    314294                        rc = VbglR3GuestCtrlMsgSkipOld(g_idControlSvcClient);
    315                         VGSvcVerbose(3, "Skipped idMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, cParms, rc);
     295                        VGSvcVerbose(3, "Skipped idMsg=%RU32, cParms=%RU32, rc=%Rrc\n", idMsg, ctxHost.uNumParms, rc);
    316296                    }
    317297                    break;
     
    325305            RTThreadYield();
    326306        }
     307        /*
     308         * Handle restore notification from host.  All the context IDs (sessions,
     309         * files, proceses, etc) are invalidated by a VM restore and must be closed.
     310         */
     311        else if (rc == VERR_VM_RESTORED)
     312        {
     313            VGSvcVerbose(1, "The VM session ID changed (i.e. restored).\n");
     314            int rc2 = VGSvcGstCtrlSessionClose(&g_Session);
     315            AssertRC(rc2);
     316        }
    327317        else
    328318        {
     
    332322
    333323            /* Check for VM session change. */
     324            /** @todo  We don't need to check the host here.  */
    334325            uint64_t idNewSession = g_idControlSession;
    335326            int rc2 = VbglR3GetSessionId(&idNewSession);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp

    r75824 r75853  
    15791579                    VGSvcVerbose(3, "Waiting for host msg ...\n");
    15801580                    uint32_t uMsg = 0;
    1581                     rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &CtxHost.uNumParms);
     1581                    rc = VbglR3GuestCtrlMsgPeekWait(idClient, &uMsg, &CtxHost.uNumParms, NULL);
    15821582                    if (RT_SUCCESS(rc))
    15831583                    {
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r75808 r75853  
    44214421    pThis->IHGCMPort.pfnIsCmdRestored       = hgcmIsCmdRestored;
    44224422    pThis->IHGCMPort.pfnGetRequestor        = hgcmGetRequestor;
     4423    pThis->IHGCMPort.pfnGetVMMDevSessionId  = hgcmGetVMMDevSessionId;
    44234424#endif
    44244425
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp

    r75808 r75853  
    15461546        return pCmd->fRequestor;
    15471547   return VMMDEV_REQUESTOR_LEGACY;
     1548}
     1549
     1550/**
     1551 * @interface_method_impl{PDMIHGCMPORT,pfnGetVMMDevSessionId}
     1552 */
     1553DECLCALLBACK(uint64_t) hgcmGetVMMDevSessionId(PPDMIHGCMPORT pInterface)
     1554{
     1555    PVMMDEV pThis = RT_FROM_MEMBER(pInterface, VMMDevState, IHGCMPort);
     1556    return pThis->idSession;
    15481557}
    15491558
  • trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.h

    r75769 r75853  
    3232DECLCALLBACK(bool) hgcmIsCmdRestored(PPDMIHGCMPORT pInterface, PVBOXHGCMCMD pCmd);
    3333DECLCALLBACK(uint32_t) hgcmGetRequestor(PPDMIHGCMPORT pInterface, PVBOXHGCMCMD pCmd);
     34DECLCALLBACK(uint64_t) hgcmGetVMMDevSessionId(PPDMIHGCMPORT pInterface);
    3435
    3536int vmmdevHGCMSaveState(VMMDevState *pVMMDevState, PSSMHANDLE pSSM);
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r75825 r75853  
    6767#include <VBox/AssertGuest.h>
    6868#include <VBox/VMMDev.h>
     69#include <VBox/vmm/ssm.h>
    6970#include <iprt/assert.h>
    7071#include <iprt/cpp/autores.h>
     
    139140    }
    140141
     142
    141143    /**
    142144     * Retains a reference to the command.
     
    149151        return cRefs;
    150152    }
     153
    151154
    152155    /**
     
    180183    }
    181184
     185
    182186    /**
    183187     * Initializes the command.
     
    269273    }
    270274
     275
     276    /**
     277     * Sets the GUEST_MSG_PEEK_WAIT GUEST_MSG_PEEK_NOWAIT return parameters.
     278     *
     279     * @param   paDstParms  The peek parameter vector.
     280     * @param   cDstParms   The number of peek parameters (at least two).
     281     * @remarks ASSUMES the parameters has been cleared by clientMsgPeek.
     282     */
     283    inline void setPeekReturn(PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
     284    {
     285        Assert(cDstParms >= 2);
     286        if (paDstParms[0].type == VBOX_HGCM_SVC_PARM_32BIT)
     287            paDstParms[0].u.uint32 = mMsgType;
     288        else
     289            paDstParms[0].u.uint64 = mMsgType;
     290        paDstParms[1].u.uint32 = mParmCount;
     291
     292        uint32_t i = RT_MIN(cDstParms, mParmCount + 2);
     293        while (i-- > 2)
     294            switch (mpParms[i - 2].type)
     295            {
     296                case VBOX_HGCM_SVC_PARM_32BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
     297                case VBOX_HGCM_SVC_PARM_64BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
     298                case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = mpParms[i - 2].u.pointer.size; break;
     299            }
     300    }
     301
     302
     303    /** @name Support for old-style (GUEST_MSG_WAIT) operation.
     304     * @{
     305     */
    271306
    272307    /**
     
    421456        return VERR_TOO_MUCH_DATA;
    422457    }
     458
     459    /** @} */
    423460} HostCommand;
    424461typedef std::list< HostCommand *> HostCmdList;
     
    527564            rc = VINF_SUCCESS;
    528565
    529             HostCmdListIter curCmd = mHostCmdList.begin();
    530             if (curCmd != mHostCmdList.end())
     566            HostCmdListIter ItFirstCmd = mHostCmdList.begin();
     567            if (ItFirstCmd != mHostCmdList.end())
    531568            {
    532                 HostCommand *pHostCmd = (*curCmd);
    533                 AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
     569                HostCommand *pFirstCmd = (*ItFirstCmd);
     570                AssertPtrReturn(pFirstCmd, VERR_INVALID_POINTER);
    534571
    535572                LogFlowThisFunc(("[Client %RU32] Current host command is %RU32 (CID=%RU32, cParms=%RU32, m_cRefs=%RU32)\n",
    536                                  mID, pHostCmd->mMsgType, pHostCmd->m_idContext, pHostCmd->mParmCount, pHostCmd->m_cRefs));
     573                                 mID, pFirstCmd->mMsgType, pFirstCmd->m_idContext, pFirstCmd->mParmCount, pFirstCmd->m_cRefs));
    537574
    538575                if (mIsPending == GUEST_MSG_PEEK_WAIT)
    539576                {
    540                     HGCMSvcSetU32(&mPendingCon.mParms[0], pHostCmd->mMsgType);
    541                     HGCMSvcSetU32(&mPendingCon.mParms[1], pHostCmd->mParmCount);
    542                     uint32_t i = RT_MIN(mPendingCon.mNumParms, pHostCmd->mParmCount + 2);
    543                     while (i-- > 2)
    544                         switch (pHostCmd->mpParms[i - 2].type)
    545                         {
    546                             case VBOX_HGCM_SVC_PARM_32BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
    547                             case VBOX_HGCM_SVC_PARM_64BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
    548                             case VBOX_HGCM_SVC_PARM_PTR:   mPendingCon.mParms[i].u.uint32 = pHostCmd->mpParms[i - 2].u.pointer.size; break;
    549                         }
    550 
     577                    pFirstCmd->setPeekReturn(mPendingCon.mParms, mPendingCon.mNumParms);
    551578                    rc = mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, VINF_SUCCESS);
    552579
     
    557584                }
    558585                else if (mIsPending == GUEST_MSG_WAIT)
    559                     rc = OldRun(&mPendingCon, pHostCmd);
     586                    rc = OldRun(&mPendingCon, pFirstCmd);
    560587                else
    561588                    AssertMsgFailed(("mIsPending=%d\n", mIsPending));
     
    654681    {
    655682        Assert(!mHostCmdList.empty());
    656         HostCommand *pHostCmd = *mHostCmdList.begin();
    657         AssertPtr(pHostCmd);
    658         pHostCmd->SaneRelease();
     683        HostCommand *pFirstCmd = *mHostCmdList.begin();
     684        AssertPtr(pFirstCmd);
     685        pFirstCmd->SaneRelease();
    659686        mHostCmdList.pop_front();
    660687
     
    879906    RTLISTANCHOR mHostCmdList;
    880907    /** Map containing all connected clients, key is HGCM client ID. */
    881     ClientStateMap  mClientStateMap;
     908    ClientStateMap  mClientStateMap; /**< @todo Use VBOXHGCMSVCFNTABLE::cbClient for this! */
    882909    /** The master HGCM client ID, UINT32_MAX if none. */
    883910    uint32_t        m_idMasterClient;
     
    909936                                      uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival);
    910937    static DECLCALLBACK(int)  svcHostCall(void *pvService, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     938    static DECLCALLBACK(int)  svcSaveState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM);
     939    static DECLCALLBACK(int)  svcLoadState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion);
    911940    static DECLCALLBACK(int)  svcRegisterExtension(void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
    912941
     
    11991228     */
    12001229    ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_WRONG_PARAMETER_COUNT);
    1201     for (uint32_t i = 0; i < cParms; i++)
     1230
     1231    uint64_t idRestoreCheck = 0;
     1232    uint32_t i              = 0;
     1233    if (paParms[i].type == VBOX_HGCM_SVC_PARM_64BIT)
     1234    {
     1235        idRestoreCheck = paParms[0].u.uint64;
     1236        paParms[0].u.uint64 = 0;
     1237        i++;
     1238    }
     1239    for (; i < cParms; i++)
    12021240    {
    12031241        ASSERT_GUEST_MSG_RETURN(paParms[i].type == VBOX_HGCM_SVC_PARM_32BIT, ("#%u type=%u\n", i, paParms[i].type),
     
    12111249
    12121250    /*
     1251     * Check restore session ID.
     1252     */
     1253    if (idRestoreCheck != 0)
     1254    {
     1255        uint64_t idRestore = mpHelpers->pfnGetVMMDevSessionId(mpHelpers);
     1256        if (idRestoreCheck != idRestore)
     1257        {
     1258            paParms[0].u.uint32 = idRestore;
     1259            LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VERR_VM_RESTORED (%#RX64 -> %#RX64)\n",
     1260                         idClient, idRestoreCheck, idRestore));
     1261            return VERR_VM_RESTORED;
     1262        }
     1263        Assert(!mpHelpers->pfnIsCallRestored(hCall));
     1264    }
     1265
     1266    /*
    12131267     * Return information about the first command if one is pending in the list.
    12141268     */
     
    12171271    {
    12181272        HostCommand *pFirstCmd = *itFirstCmd;
    1219         paParms[0].u.uint32 = pFirstCmd->mMsgType;
    1220         paParms[1].u.uint32 = pFirstCmd->mParmCount;
    1221         uint32_t i = RT_MIN(cParms, pFirstCmd->mParmCount + 2);
    1222         while (i-- > 2)
    1223             switch (pFirstCmd->mpParms[i - 2].type)
    1224             {
    1225                 case VBOX_HGCM_SVC_PARM_32BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
    1226                 case VBOX_HGCM_SVC_PARM_64BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
    1227                 case VBOX_HGCM_SVC_PARM_PTR:   paParms[i].u.uint32 = pFirstCmd->mpParms[i - 2].u.pointer.size; break;
    1228             }
    1229 
     1273        pFirstCmd->setPeekReturn(paParms, cParms);
    12301274        LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n",
    12311275                     idClient, pFirstCmd->mMsgType, GstCtrlHostFnName((eHostFn)pFirstCmd->mMsgType), pFirstCmd->mParmCount));
     
    21972241
    21982242/**
     2243 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnSaveState}
     2244 */
     2245/*static*/ DECLCALLBACK(int)
     2246GstCtrlService::svcSaveState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM)
     2247{
     2248    RT_NOREF(pvClient);
     2249    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     2250    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     2251    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2252
     2253    SSMR3PutU32(pSSM, 1);
     2254    SSMR3PutBool(pSSM, idClient == pThis->m_idMasterClient);
     2255    return SSMR3PutBool(pSSM, pThis->m_fLegacyMode);
     2256}
     2257
     2258
     2259/**
     2260 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnLoadState}
     2261 */
     2262/*static*/ DECLCALLBACK(int)
     2263GstCtrlService::svcLoadState(void *pvService, uint32_t idClient, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion)
     2264{
     2265    RT_NOREF(pvClient);
     2266    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
     2267    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     2268    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2269
     2270    if (uVersion >= HGCM_SAVED_STATE_VERSION)
     2271    {
     2272        uint32_t uSubVersion;
     2273        int rc = SSMR3GetU32(pSSM, &uSubVersion);
     2274        AssertRCReturn(rc, rc);
     2275        if (uSubVersion != 1)
     2276            return SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS,
     2277                                     "sub version %u, expected 1\n", uSubVersion);
     2278        bool fLegacyMode;
     2279        rc = SSMR3GetBool(pSSM, &fLegacyMode);
     2280        AssertRCReturn(rc, rc);
     2281        pThis->m_fLegacyMode = fLegacyMode;
     2282
     2283        bool fIsMaster;
     2284        rc = SSMR3GetBool(pSSM, &fIsMaster);
     2285        AssertRCReturn(rc, rc);
     2286        if (fIsMaster)
     2287            pThis->m_idMasterClient = idClient;
     2288        ClientStateMapIter It = pThis->mClientStateMap.find(idClient);
     2289        if (It != pThis->mClientStateMap.end())
     2290            It->second.m_fIsMaster = fIsMaster;
     2291        else
     2292            AssertFailed();
     2293    }
     2294    else
     2295    {
     2296        /*
     2297         * For old saved states we have to guess at who should be the master.
     2298         * Given how HGCMService::CreateAndConnectClient and associates manage
     2299         * and saves the client, the first client connecting will be restored
     2300         * first.  The only time this might go wrong if the there are zombie
     2301         * VBoxService session processes in the restored guest, and I don't
     2302         * we need to care too much about that scenario.
     2303         *
     2304         * Given how HGCM first re-connects the clients before this function
     2305         * gets called, there isn't anything we need to do here it turns out. :-)
     2306         */
     2307    }
     2308    return VINF_SUCCESS;
     2309}
     2310
     2311
     2312/**
    21992313 * @interface_method_impl{VBOXHGCMSVCFNTABLE,pfnRegisterExtension,
    22002314 *  Installs a host callback for notifications of property changes.}
     
    22032317{
    22042318    AssertLogRelReturn(VALID_PTR(pvService), VERR_INVALID_PARAMETER);
    2205     SELF *pSelf = reinterpret_cast<SELF *>(pvService);
    2206     AssertPtrReturn(pSelf, VERR_INVALID_POINTER);
    2207     pSelf->mpfnHostCallback = pfnExtension;
    2208     pSelf->mpvHostData = pvExtension;
     2319    SELF *pThis = reinterpret_cast<SELF *>(pvService);
     2320    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     2321
     2322    pThis->mpfnHostCallback = pfnExtension;
     2323    pThis->mpvHostData = pvExtension;
    22092324    return VINF_SUCCESS;
    22102325}
     
    22562371                 * because we're a class which can have members for that :-).
    22572372                 */
    2258                 pTable->cbClient = 0;
     2373                pTable->cbClient = 0;  /** @todo this is where ClientState should live, isn't it? */
    22592374
    22602375                /* Register functions. */
    2261                 pTable->pfnUnload             = GstCtrlService::svcUnload;
    2262                 pTable->pfnConnect            = GstCtrlService::svcConnect;
    2263                 pTable->pfnDisconnect         = GstCtrlService::svcDisconnect;
    2264                 pTable->pfnCall               = GstCtrlService::svcCall;
    2265                 pTable->pfnHostCall           = GstCtrlService::svcHostCall;
    2266                 pTable->pfnSaveState          = NULL;  /* The GstCtrlService is stateless, so the normal */
    2267                 pTable->pfnLoadState          = NULL;  /* construction done before restoring suffices */
    2268                 pTable->pfnRegisterExtension  = GstCtrlService::svcRegisterExtension;
     2376                pTable->pfnUnload               = GstCtrlService::svcUnload;
     2377                pTable->pfnConnect              = GstCtrlService::svcConnect;
     2378                pTable->pfnDisconnect           = GstCtrlService::svcDisconnect;
     2379                pTable->pfnCall                 = GstCtrlService::svcCall;
     2380                pTable->pfnHostCall             = GstCtrlService::svcHostCall;
     2381                pTable->pfnSaveState            = GstCtrlService::svcSaveState;
     2382                pTable->pfnLoadState            = GstCtrlService::svcLoadState;
     2383                pTable->pfnRegisterExtension    = GstCtrlService::svcRegisterExtension;
    22692384
    22702385                /* Service specific initialization. */
  • trunk/src/VBox/HostServices/GuestControl/testcase/Makefile.kmk

    r69111 r75853  
    3535        ../service.cpp \
    3636        tstGuestControlSvc.cpp
    37  tstGuestControlSvc_LIBS     = $(LIB_RUNTIME)
     37 tstGuestControlSvc_LIBS     = $(LIB_RUNTIME) $(LIB_VMM)
    3838
    3939$$(tstGuestControlSvc_0_OUTDIR)/tstGuestControlSvc.run: $$(tstGuestControlSvc_1_STAGE_TARGET)
  • trunk/src/VBox/HostServices/SharedClipboard/service.cpp

    r75773 r75853  
    857857} CLIPSAVEDSTATEDATA;
    858858
    859 static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
     859static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion)
    860860{
    861861#ifndef UNIT_TEST
     862    RT_NOREF(uVersion);
    862863    LogRel2 (("svcLoadState: u32ClientID = %d\n", u32ClientID));
    863864
     
    931932
    932933#else  /* UNIT_TEST*/
    933     RT_NOREF3(u32ClientID, pvClient, pSSM);
     934    RT_NOREF(u32ClientID, pvClient, pSSM, uVersion);
    934935#endif /* UNIT_TEST */
    935936    return VINF_SUCCESS;
  • trunk/src/VBox/HostServices/SharedFolders/service.cpp

    r75773 r75853  
    242242}
    243243
    244 static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
     244static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion)
    245245{
    246246#ifndef UNITTEST  /* Read this as not yet tested */
    247     RT_NOREF1(u32ClientID);
     247    RT_NOREF(u32ClientID, uVersion);
    248248    uint32_t        nrMappings;
    249249    SHFLCLIENTDATA *pClient = (SHFLCLIENTDATA *)pvClient;
     
    395395    Log(("SharedFolders host service: successfully loaded state\n"));
    396396#else
    397     RT_NOREF3(u32ClientID, pvClient, pSSM);
     397    RT_NOREF(u32ClientID, pvClient, pSSM, uVersion);
    398398#endif
    399399    return VINF_SUCCESS;
  • trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp

    r75773 r75853  
    199199}
    200200
    201 static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
     201static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM, uint32_t uVersion)
    202202{
     203    RT_NOREF(pvClient, uVersion);
    203204    int rc = VINF_SUCCESS;
    204 
    205     NOREF(pvClient);
    206205
    207206    Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r75527 r75853  
    740740    int i_configSerialPort(PCFGMNODE pInst, PortMode_T ePortMode, const char *pszPath, bool fServer);
    741741    static DECLCALLBACK(int) i_configGuestProperties(void *pvConsole);
    742     static DECLCALLBACK(int) i_configGuestControl(void *pvConsole);
    743742    static DECLCALLBACK(void) i_vmstateChangeCallback(PUVM pUVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
    744743    static DECLCALLBACK(int) i_unplugCpu(Console *pThis, PUVM pUVM, VMCPUID idCpu);
  • trunk/src/VBox/Main/include/HGCM.h

    r75574 r75853  
    2626#include <VBox/hgcmsvc.h>
    2727
    28 /* HGCM saved state version */
    29 #define HGCM_SSM_VERSION    2
    30 
    3128/* Handle of a HGCM service extension. */
    3229struct _HGCMSVCEXTHANDLEDATA;
     
    3936int HGCMHostReset(void);
    4037
    41 int HGCMHostLoad(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM);
     38int HGCMHostLoad(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM, PPDMIHGCMPORT pHgcmPort);
    4239
    4340int HGCMHostRegisterServiceExtension(HGCMSVCEXTHANDLE *pHandle, const char *pszServiceName, PFNHGCMSVCEXT pfnExtension, void *pvExtension);
     
    5956
    6057int HGCMHostSaveState(PSSMHANDLE pSSM);
    61 int HGCMHostLoadState(PSSMHANDLE pSSM);
     58int HGCMHostLoadState(PSSMHANDLE pSSM, uint32_t uVersion);
    6259
    6360RT_C_DECLS_END
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r75823 r75853  
    3636#include "ConsoleImpl.h"
    3737#include "DisplayImpl.h"
    38 #ifdef VBOX_WITH_GUEST_CONTROL
     38#ifdef VBOX_WITH_DRAG_AND_DROP
    3939# include "GuestImpl.h"
    40 #endif
    41 #ifdef VBOX_WITH_DRAG_AND_DROP
    4240# include "GuestDnDPrivate.h"
    4341#endif
     
    31943192         */
    31953193        rc = i_configGuestProperties(this);
    3196 #endif
    3197 
    3198 #ifdef VBOX_WITH_GUEST_CONTROL
    3199         /*
    3200          * Guest control service.
    3201          */
    3202         rc = i_configGuestControl(this);
    32033194#endif
    32043195
     
    62356226}
    62366227
    6237 /**
    6238  * Set up the Guest Control service.
    6239  */
    6240 /* static */ int Console::i_configGuestControl(void *pvConsole)
    6241 {
    6242 #ifdef VBOX_WITH_GUEST_CONTROL
    6243     AssertReturn(pvConsole, VERR_INVALID_POINTER);
    6244     ComObjPtr<Console> pConsole = static_cast<Console *>(pvConsole);
    6245 
    6246     /* Load the service */
    6247     int rc = pConsole->m_pVMMDev->hgcmLoadService("VBoxGuestControlSvc", "VBoxGuestControlSvc");
    6248 
    6249     if (RT_FAILURE(rc))
    6250     {
    6251         LogRel(("VBoxGuestControlSvc is not available. rc = %Rrc\n", rc));
    6252         /* That is not a fatal failure. */
    6253         rc = VINF_SUCCESS;
    6254     }
    6255     else
    6256     {
    6257         HGCMSVCEXTHANDLE hDummy;
    6258         rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc",
    6259                                               &Guest::i_notifyCtrlDispatcher,
    6260                                               pConsole->i_getGuest());
    6261         if (RT_FAILURE(rc))
    6262             Log(("Cannot register VBoxGuestControlSvc extension!\n"));
    6263         else
    6264             LogRel(("Guest Control service loaded\n"));
    6265     }
    6266 
    6267     return rc;
    6268 #else /* !VBOX_WITH_GUEST_CONTROL */
    6269     return VERR_NOT_SUPPORTED;
    6270 #endif /* !VBOX_WITH_GUEST_CONTROL */
    6271 }
  • trunk/src/VBox/Main/src-client/HGCM.cpp

    r75774 r75853  
    118118
    119119        PUVM m_pUVM;
     120        PPDMIHGCMPORT m_pHgcmPort;
    120121
    121122        /** @name Statistics
     
    130131         * Main HGCM thread methods.
    131132         */
    132         int instanceCreate(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM);
     133        int instanceCreate(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM, PPDMIHGCMPORT pHgcmPort);
    133134        void instanceDestroy(void);
    134135
    135136        int saveClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
    136         int loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM);
     137        int loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM, uint32_t uVersion);
    137138
    138139        HGCMService();
     
    150151        static DECLCALLBACK(int)  svcHlpInfoDeregister(void *pvInstance, const char *pszName);
    151152        static DECLCALLBACK(uint32_t) svcHlpGetRequestor(VBOXHGCMCALLHANDLE hCall);
     153        static DECLCALLBACK(uint64_t) svcHlpGetVMMDevSessionId(void *pvInstance);
    152154
    153155    public:
     
    156158         * Main HGCM thread methods.
    157159         */
    158         static int LoadService(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM);
     160        static int LoadService(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM, PPDMIHGCMPORT pHgcmPort);
    159161        void UnloadService(bool fUvmIsInvalid);
    160162
     
    168170
    169171        static int SaveState(PSSMHANDLE pSSM);
    170         static int LoadState(PSSMHANDLE pSSM);
     172        static int LoadState(PSSMHANDLE pSSM, uint32_t uVersion);
    171173
    172174        int CreateAndConnectClient(uint32_t *pu32ClientIdOut, uint32_t u32ClientIdIn, uint32_t fRequestor, bool fRestoring);
     
    199201{
    200202    public:
    201         HGCMClient() : HGCMObject(HGCMOBJ_CLIENT), pService(NULL),
    202                         pvData(NULL) {};
     203        HGCMClient(uint32_t a_fRequestor)
     204            : HGCMObject(HGCMOBJ_CLIENT)
     205            , pService(NULL)
     206            , pvData(NULL)
     207            , fRequestor(a_fRequestor)
     208        {}
    203209        ~HGCMClient();
    204210
     
    210216        /** Client specific data. */
    211217        void *pvData;
     218
     219        /** The requestor flags this client was created with.
     220         * @sa VMMDevRequestHeader::fRequestor */
     221        uint32_t fRequestor;
     222
     223    private: /* none of this: */
     224        HGCMClient();
     225        HGCMClient(HGCMClient const &);
     226        HGCMClient &operator=(HGCMClient const &);
    212227};
    213228
     
    215230{
    216231    if (pService->SizeOfClient() > 0)
     232    {
    217233        RTMemFree(pvData);
    218 }
     234        pvData = NULL;
     235    }
     236}
     237
    219238
    220239int HGCMClient::Init(HGCMService *pSvc)
     
    261280#endif
    262281    m_hExtension (NULL),
    263     m_pUVM       (NULL)
     282    m_pUVM       (NULL),
     283    m_pHgcmPort  (NULL)
    264284{
    265285    RT_ZERO(m_fntable);
     
    469489{
    470490    public:
     491        PSSMHANDLE  pSSM;
     492        uint32_t    uVersion;
    471493        uint32_t    u32ClientId;
    472         PSSMHANDLE  pSSM;
    473494};
    474495
     
    684705                if (pClient)
    685706                {
    686                     if (pSvc->m_fntable.pfnLoadState)
     707                    /* fRequestor: Restored by the message sender already. */
     708                    bool fHaveClientState = pSvc->m_fntable.pfnLoadState != NULL;
     709                    if (pMsg->uVersion > HGCM_SAVED_STATE_VERSION_V2)
     710                        rc = SSMR3GetBool(pMsg->pSSM, &fHaveClientState);
     711                    else
     712                        rc = VINF_SUCCESS;
     713                    if (RT_SUCCESS(rc) )
    687714                    {
    688                         rc = pSvc->m_fntable.pfnLoadState(pSvc->m_fntable.pvService, pMsg->u32ClientId,
    689                                                           HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM);
     715                        if (pSvc->m_fntable.pfnLoadState)
     716                            rc = pSvc->m_fntable.pfnLoadState(pSvc->m_fntable.pvService, pMsg->u32ClientId,
     717                                                              HGCM_CLIENT_DATA(pSvc, pClient), pMsg->pSSM,
     718                                                              fHaveClientState ? pMsg->uVersion : 0);
     719                        else
     720                            AssertLogRelStmt(!fHaveClientState, rc = VERR_INTERNAL_ERROR_5);
    690721                    }
    691 
    692722                    hgcmObjDereference(pClient);
    693723                }
     
    710740                if (pClient)
    711741                {
    712                     if (pSvc->m_fntable.pfnSaveState)
     742                    SSMR3PutU32(pMsg->pSSM, pClient->fRequestor); /* Quicker to save this here than in the message sender. */
     743                    rc = SSMR3PutBool(pMsg->pSSM, pSvc->m_fntable.pfnSaveState != NULL);
     744                    if (RT_SUCCESS(rc) && pSvc->m_fntable.pfnSaveState)
    713745                    {
    714746                        g_fSaveState = true;
     
    893925}
    894926
    895 
    896927/**
    897928 * @interface_method_impl{VBOXHGCMSVCHELPERS,pfnGetRequestor}
     
    909940
    910941    return pHgcmPort->pfnGetRequestor(pHgcmPort, pCmd);
     942}
     943
     944/**
     945 * @interface_method_impl{VBOXHGCMSVCHELPERS,pfnGetVMMDevSessionId}
     946 */
     947/* static */ DECLCALLBACK(uint64_t) HGCMService::svcHlpGetVMMDevSessionId(void *pvInstance)
     948{
     949     HGCMService *pService = static_cast <HGCMService *>(pvInstance);
     950     AssertPtrReturn(pService, UINT64_MAX);
     951
     952     PPDMIHGCMPORT pHgcmPort = pService->m_pHgcmPort;
     953     AssertPtrReturn(pHgcmPort, UINT64_MAX);
     954
     955     return pHgcmPort->pfnGetVMMDevSessionId(pHgcmPort);
    911956}
    912957
     
    933978 */
    934979
    935 int HGCMService::instanceCreate(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM)
     980int HGCMService::instanceCreate(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM, PPDMIHGCMPORT pHgcmPort)
    936981{
    937982    LogFlowFunc(("name %s, lib %s\n", pszServiceName, pszServiceLibrary));
     
    9641009        else
    9651010        {
     1011            m_pUVM = pUVM;
     1012            m_pHgcmPort = pHgcmPort;
     1013
    9661014            /* Register statistics: */
    967             m_pUVM = pUVM;
    9681015            STAMR3RegisterFU(pUVM, &m_StatHandleMsg, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
    9691016                             "Message handling", "/HGCM/%s/Msg", pszServiceName);
    9701017
    9711018            /* Initialize service helpers table. */
    972             m_svcHelpers.pfnCallComplete     = svcHlpCallComplete;
    973             m_svcHelpers.pvInstance          = this;
    974             m_svcHelpers.pfnDisconnectClient = svcHlpDisconnectClient;
    975             m_svcHelpers.pfnIsCallRestored   = svcHlpIsCallRestored;
    976             m_svcHelpers.pfnStamRegisterV    = svcHlpStamRegisterV;
    977             m_svcHelpers.pfnStamDeregisterV  = svcHlpStamDeregisterV;
    978             m_svcHelpers.pfnInfoRegister     = svcHlpInfoRegister;
    979             m_svcHelpers.pfnInfoDeregister   = svcHlpInfoDeregister;
    980             m_svcHelpers.pfnGetRequestor     = svcHlpGetRequestor;
     1019            m_svcHelpers.pfnCallComplete       = svcHlpCallComplete;
     1020            m_svcHelpers.pvInstance            = this;
     1021            m_svcHelpers.pfnDisconnectClient   = svcHlpDisconnectClient;
     1022            m_svcHelpers.pfnIsCallRestored     = svcHlpIsCallRestored;
     1023            m_svcHelpers.pfnStamRegisterV      = svcHlpStamRegisterV;
     1024            m_svcHelpers.pfnStamDeregisterV    = svcHlpStamDeregisterV;
     1025            m_svcHelpers.pfnInfoRegister       = svcHlpInfoRegister;
     1026            m_svcHelpers.pfnInfoDeregister     = svcHlpInfoDeregister;
     1027            m_svcHelpers.pfnGetRequestor       = svcHlpGetRequestor;
     1028            m_svcHelpers.pfnGetVMMDevSessionId = svcHlpGetVMMDevSessionId;
    9811029
    9821030            /* Execute the load request on the service thread. */
     
    10221070        STAMR3DeregisterF(m_pUVM, "/HGCM/%s/*", m_pszSvcName);
    10231071    m_pUVM = NULL;
     1072    m_pHgcmPort = NULL;
    10241073
    10251074    RTStrFree(m_pszSvcLibrary);
     
    10511100}
    10521101
    1053 int HGCMService::loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM)
     1102int HGCMService::loadClientState(uint32_t u32ClientId, PSSMHANDLE pSSM, uint32_t uVersion)
    10541103{
    10551104    LogFlowFunc(("%s\n", m_pszSvcName));
     
    10621111        HGCMMsgLoadSaveStateClient *pMsg = (HGCMMsgLoadSaveStateClient *)pCoreMsg;
    10631112
     1113        pMsg->pSSM        = pSSM;
     1114        pMsg->uVersion    = uVersion;
    10641115        pMsg->u32ClientId = u32ClientId;
    1065         pMsg->pSSM        = pSSM;
    10661116
    10671117        rc = hgcmMsgSend(pMsg);
     
    10751125/** The method creates a service and references it.
    10761126 *
    1077  * @param pszServiceLibrary  The library to be loaded.
    1078  * @param pszServiceName     The name of the service.
    1079  * @param pUVM               The user mode VM handle (for statistics and such).
    1080  * @return VBox rc.
    1081  * @thread main HGCM
    1082  */
    1083 /* static */ int HGCMService::LoadService(const char *pszServiceLibrary, const char *pszServiceName, PUVM pUVM)
     1127 * @param   pszServiceLibrary  The library to be loaded.
     1128 * @param   pszServiceName     The name of the service.
     1129 * @param   pUVM               The user mode VM handle (for statistics and such).
     1130 * @param   pHgcmPort          The VMMDev HGCM port interface.
     1131 *
     1132 * @return  VBox rc.
     1133 * @thread  main HGCM
     1134 */
     1135/* static */ int HGCMService::LoadService(const char *pszServiceLibrary, const char *pszServiceName,
     1136                                          PUVM pUVM, PPDMIHGCMPORT pHgcmPort)
    10841137{
    10851138    LogFlowFunc(("lib %s, name = %s, pUVM = %p\n", pszServiceLibrary, pszServiceName, pUVM));
     
    11081161        {
    11091162            /* Load the library and call the initialization entry point. */
    1110             rc = pSvc->instanceCreate(pszServiceLibrary, pszServiceName, pUVM);
     1163            rc = pSvc->instanceCreate(pszServiceLibrary, pszServiceName, pUVM, pHgcmPort);
    11111164
    11121165            if (RT_SUCCESS(rc))
     
    11511204
    11521205    if (fUvmIsInvalid)
     1206    {
    11531207        m_pUVM = NULL;
     1208        m_pHgcmPort = NULL;
     1209    }
    11541210
    11551211    /* Remove the service from the list. */
     
    13541410            Log(("client id 0x%08X\n", u32ClientId));
    13551411
    1356             /* Save the client id. */
     1412            /* Save the client id. (fRequestor is saved via SVC_MSG_SAVESTATE for convenience.) */
    13571413            rc = SSMR3PutU32(pSSM, u32ClientId);
    13581414            AssertRCReturn(rc, rc);
     
    13711427/** The method loads saved HGCM state.
    13721428 *
    1373  * @param pSSM  The saved state context.
     1429 * @param pSSM      The saved state handle.
     1430 * @param uVersion  The state version being loaded.
    13741431 * @return VBox rc.
    13751432 * @thread main HGCM
    13761433 */
    1377 /* static */ int HGCMService::LoadState(PSSMHANDLE pSSM)
     1434/* static */ int HGCMService::LoadState(PSSMHANDLE pSSM, uint32_t uVersion)
    13781435{
    13791436    /* Restore handle count to avoid client id conflicts. */
     
    14241481        while (cClients--)
    14251482        {
    1426             /* Get the client id. */
     1483            /* Get the client ID and fRequest (convieniently save via SVC_MSG_SAVESTATE
     1484               but restored here in time for calling CreateAndConnectClient). */
    14271485            uint32_t u32ClientId;
    14281486            rc = SSMR3GetU32(pSSM, &u32ClientId);
    1429             uint32_t fRequestor = VMMDEV_REQUESTOR_LEGACY; /** @todo save/restore fRequestor. */
    1430             if (RT_FAILURE(rc))
    1431             {
    1432                 pSvc->ReleaseService();
    1433                 AssertFailed();
    1434                 return rc;
    1435             }
     1487            uint32_t fRequestor = VMMDEV_REQUESTOR_LEGACY;
     1488            if (RT_SUCCESS(rc) && uVersion > HGCM_SAVED_STATE_VERSION_V2)
     1489                rc = SSMR3GetU32(pSSM, &fRequestor);
     1490            AssertLogRelMsgRCReturnStmt(rc, ("rc=%Rrc, %s\n", rc, szServiceName), pSvc->ReleaseService(), rc);
    14361491
    14371492            /* Connect the client. */
    14381493            rc = pSvc->CreateAndConnectClient(NULL, u32ClientId, fRequestor, true /*fRestoring*/);
    1439             if (RT_FAILURE(rc))
    1440             {
    1441                 pSvc->ReleaseService();
    1442                 AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, szServiceName));
    1443                 return rc;
    1444             }
     1494            AssertLogRelMsgRCReturnStmt(rc, ("rc=%Rrc, %s\n", rc, szServiceName), pSvc->ReleaseService(), rc);
    14451495
    14461496            /* Call the service, so the operation is executed by the service thread. */
    1447             rc = pSvc->loadClientState(u32ClientId, pSSM);
    1448             if (RT_FAILURE(rc))
    1449             {
    1450                 pSvc->ReleaseService();
    1451                 AssertLogRelMsgFailed(("rc=%Rrc %s\n", rc, szServiceName));
    1452                 return rc;
    1453             }
     1497            rc = pSvc->loadClientState(u32ClientId, pSSM, uVersion);
     1498            AssertLogRelMsgRCReturnStmt(rc, ("rc=%Rrc, %s\n", rc, szServiceName), pSvc->ReleaseService(), rc);
    14541499        }
    14551500
     
    14751520
    14761521    /* Allocate a client information structure. */
    1477     HGCMClient *pClient = new HGCMClient();
     1522    HGCMClient *pClient = new (std::nothrow) HGCMClient(fRequestor);
    14781523
    14791524    if (!pClient)
     
    18511896        /** The user mode VM handle (for statistics and such). */
    18521897        PUVM pUVM;
     1898        /** The HGCM port on the VMMDev device (for session ID and such). */
     1899        PPDMIHGCMPORT pHgcmPort;
    18531900};
    18541901
     
    18691916{
    18701917    public:
    1871         /* SSM context. */
     1918        /** Saved state handle. */
    18721919        PSSMHANDLE pSSM;
     1920        /** The HGCM saved state version being loaded (ignore for save). */
     1921        uint32_t uVersion;
    18731922};
    18741923
     
    20312080                             pMsg->pszServiceName, pMsg->pszServiceLibrary, pMsg->pUVM));
    20322081
    2033                 rc = HGCMService::LoadService(pMsg->pszServiceLibrary, pMsg->pszServiceName, pMsg->pUVM);
     2082                rc = HGCMService::LoadService(pMsg->pszServiceLibrary, pMsg->pszServiceName, pMsg->pUVM, pMsg->pHgcmPort);
    20342083            } break;
    20352084
     
    21062155                LogFlowFunc(("HGCM_MSG_LOADSTATE\n"));
    21072156
    2108                 rc = HGCMService::LoadState(pMsg->pSSM);
     2157                rc = HGCMService::LoadState(pMsg->pSSM, pMsg->uVersion);
    21092158            } break;
    21102159
     
    22232272 * @param pszServiceName     The name to be assigned to the service.
    22242273 * @param pUVM               The user mode VM handle (for statistics and such).
     2274 * @param pHgcmPort          The HGCM port on the VMMDev device (for session ID and such).
    22252275 * @return VBox rc.
    22262276 */
    22272277int HGCMHostLoad(const char *pszServiceLibrary,
    22282278                 const char *pszServiceName,
    2229                  PUVM pUVM)
     2279                 PUVM pUVM,
     2280                 PPDMIHGCMPORT pHgcmPort)
    22302281{
    22312282    LogFlowFunc(("lib = %s, name = %s\n", pszServiceLibrary, pszServiceName));
     
    22482299        pMsg->pszServiceName    = pszServiceName;
    22492300        pMsg->pUVM              = pUVM;
     2301        pMsg->pHgcmPort         = pHgcmPort;
    22502302
    22512303        rc = hgcmMsgSend(pMsg);
     
    24032455}
    24042456
    2405 /* Helper to send either HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE messages to the main HGCM thread.
     2457/** Helper to send either HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE messages to the main HGCM thread.
    24062458 *
    24072459 * @param pSSM     The SSM handle.
    2408  * @param u32MsgId The message to be sent: HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE.
     2460 * @param idMsg    The message to be sent: HGCM_MSG_SAVESTATE or HGCM_MSG_LOADSTATE.
     2461 * @param uVersion The state version being loaded.
    24092462 * @return VBox rc.
    24102463 */
    2411 static int hgcmHostLoadSaveState(PSSMHANDLE pSSM,
    2412                                  uint32_t u32MsgId)
    2413 {
    2414     LogFlowFunc(("pSSM = %p, u32MsgId = %d\n", pSSM, u32MsgId));
     2464static int hgcmHostLoadSaveState(PSSMHANDLE pSSM, uint32_t idMsg, uint32_t uVersion)
     2465{
     2466    LogFlowFunc(("pSSM = %p, idMsg = %d, uVersion = uVersion\n", pSSM, idMsg));
    24152467
    24162468    HGCMMsgCore *pCoreMsg;
    2417     int rc = hgcmMsgAlloc(g_pHgcmThread, &pCoreMsg, u32MsgId, hgcmMainMessageAlloc);
     2469    int rc = hgcmMsgAlloc(g_pHgcmThread, &pCoreMsg, idMsg, hgcmMainMessageAlloc);
    24182470
    24192471    if (RT_SUCCESS(rc))
     
    24232475
    24242476        pMsg->pSSM = pSSM;
     2477        pMsg->uVersion = uVersion;
    24252478
    24262479        rc = hgcmMsgSend(pMsg);
     
    24312484}
    24322485
    2433 /* Save the state of services.
     2486/** Save the state of services.
    24342487 *
    24352488 * @param pSSM     The SSM handle.
     
    24382491int HGCMHostSaveState(PSSMHANDLE pSSM)
    24392492{
    2440     return hgcmHostLoadSaveState(pSSM, HGCM_MSG_SAVESTATE);
    2441 }
    2442 
    2443 /* Load the state of services.
     2493    return hgcmHostLoadSaveState(pSSM, HGCM_MSG_SAVESTATE, HGCM_SAVED_STATE_VERSION);
     2494}
     2495
     2496/** Load the state of services.
    24442497 *
    24452498 * @param pSSM     The SSM handle.
     2499 * @param uVersion The state version being loaded.
    24462500 * @return VBox rc.
    24472501 */
    2448 int HGCMHostLoadState(PSSMHANDLE pSSM)
    2449 {
    2450     return hgcmHostLoadSaveState(pSSM, HGCM_MSG_LOADSTATE);
     2502int HGCMHostLoadState(PSSMHANDLE pSSM, uint32_t uVersion)
     2503{
     2504    return hgcmHostLoadSaveState(pSSM, HGCM_MSG_LOADSTATE, uVersion);
    24512505}
    24522506
  • trunk/src/VBox/Main/src-client/VMMDevInterface.cpp

    r75574 r75853  
    680680    LogFlowFunc(("Enter\n"));
    681681
    682     if (uVersion != HGCM_SSM_VERSION)
     682    if (   uVersion != HGCM_SAVED_STATE_VERSION
     683        && uVersion != HGCM_SAVED_STATE_VERSION_V2)
    683684        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    684685    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    685686
    686     return HGCMHostLoadState(pSSM);
     687    return HGCMHostLoadState(pSSM, uVersion);
    687688}
    688689
     
    692693        return VERR_INVALID_STATE;
    693694
     695    /** @todo Construct all the services in the VMMDev::drvConstruct()!! */
     696    Assert(   (mpDrv && mpDrv->pHGCMPort)
     697           || !strcmp(pszServiceLibrary, "VBoxHostChannel")
     698           || !strcmp(pszServiceLibrary, "VBoxSharedClipboard")
     699           || !strcmp(pszServiceLibrary, "VBoxDragAndDropSvc")
     700           || !strcmp(pszServiceLibrary, "VBoxGuestPropSvc")
     701           || !strcmp(pszServiceLibrary, "VBoxSharedCrOpenGL")
     702           );
    694703    Console::SafeVMPtrQuiet ptrVM(mParent);
    695     return HGCMHostLoad(pszServiceLibrary, pszServiceName, ptrVM.rawUVM());
     704    return HGCMHostLoad(pszServiceLibrary, pszServiceName, ptrVM.rawUVM(), mpDrv ? mpDrv->pHGCMPort : NULL);
    696705}
    697706
     
    864873
    865874#ifdef VBOX_WITH_HGCM
    866     rc = pThis->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL,
    867                                          "VBoxSharedFolders");
     875    /*
     876     * Load & configure the shared folders service.
     877     */
     878    rc = pThis->pVMMDev->hgcmLoadService(VBOXSHAREDFOLDERS_DLL, "VBoxSharedFolders");
    868879    pThis->pVMMDev->fSharedFolderActive = RT_SUCCESS(rc);
    869880    if (RT_SUCCESS(rc))
     
    892903        LogRel(("Failed to load Shared Folders service %Rrc\n", rc));
    893904
    894     rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SSM_VERSION, 4096 /* bad guess */,
     905
     906    /*
     907     * Load and configure guest control service.
     908     */
     909# ifdef VBOX_WITH_GUEST_CONTROL
     910    rc = pThis->pVMMDev->hgcmLoadService("VBoxGuestControlSvc", "VBoxGuestControlSvc");
     911    if (RT_SUCCESS(rc))
     912    {
     913        HGCMSVCEXTHANDLE hDummy;
     914        rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc",
     915                                              &Guest::i_notifyCtrlDispatcher,
     916                                              pThis->pVMMDev->mParent->i_getGuest());
     917        if (RT_SUCCESS(rc))
     918            LogRel(("Guest Control service loaded\n"));
     919        else
     920            LogRel(("Warning: Cannot register VBoxGuestControlSvc extension! rc=%Rrc\n", rc));
     921    }
     922    else
     923        LogRel(("Warning!: Failed to load the Guest Control Service! %Rrc\n", rc));
     924# endif /* VBOX_WITH_GUEST_CONTROL */
     925
     926
     927    /*
     928     * The HGCM saved state.
     929     */
     930    rc = PDMDrvHlpSSMRegisterEx(pDrvIns, HGCM_SAVED_STATE_VERSION, 4096 /* bad guess */,
    895931                                NULL, NULL, NULL,
    896932                                NULL, iface_hgcmSave, NULL,
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