VirtualBox

Changeset 75755 in vbox


Ignore:
Timestamp:
Nov 27, 2018 1:36:00 AM (6 years ago)
Author:
vboxsync
Message:

GuestControlSvc: Defined 4 new commands that will succeed GUEST_MSG_WAIT - completely untested.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/GuestControlSvc.h

    r71364 r75755  
    221221     *       when used in the first capacity.
    222222     *
    223      * @todo r=bird: Next time this interface gets a major adjustment, please split
    224      *       this function up into two calls and, for heavens sake, make them return
    225      *       VINF_SUCCESS on success.
     223     * @note Has a problem if the guest kernel module cancels the HGCM call, as the
     224     *       guest cannot resume waiting till the host issues a message for it and
     225     *       the cancelled call returns.  The new message may potentially end up in
     226     *       /dev/null depending and hang the message conversation between the guest
     227     *       and the host (SIGCHLD).
     228     *
     229     * @deprecated Replaced by GUEST_MSG_PEEK_WAIT, GUEST_MSG_GET and
     230     *             GUEST_MSG_CANCEL.
    226231     */
    227232    GUEST_MSG_WAIT = 1,
     
    263268     */
    264269    GUEST_MSG_PROGRESS_UPDATE = 12,
     270
     271    /** Peeks at the next message, returning immediately.
     272     *
     273     * Returns two 32-bit parameters, first is the message ID and the second the
     274     * parameter count.  May optionally return additional 32-bit parameters with the
     275     * sizes of respective message parameters.  To distinguish buffer sizes from
     276     * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
     277     * uint64_t is ~8U).
     278     *
     279     * @retval  VINF_SUCCESS if a message was pending and is being returned.
     280     * @retval  VERR_TRY_AGAIN if no message pending.
     281     * @retval  VERR_INVALID_HANDLE if invalid client ID.
     282     * @retval  VERR_INVALID_PARAMETER if incorrect parameter count or types.
     283     * @since   6.0
     284     */
     285    GUEST_MSG_PEEK_NOWAIT,
     286    /** Peeks at the next message, waiting for one to arrive.
     287     *
     288     * Returns two 32-bit parameters, first is the message ID and the second the
     289     * parameter count.  May optionally return additional 32-bit parameters with the
     290     * sizes of respective message parameters.  To distinguish buffer sizes from
     291     * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
     292     * uint64_t is ~8U).
     293     *
     294     * @retval  VINF_SUCCESS if info about an pending message is being returned.
     295     * @retval  VINF_TRY_AGAIN and message set to HOST_CANCEL_PENDING_WAITS if
     296     *          cancelled by GUEST_MSG_CANCEL or GUEST_CANCEL_PENDING_WAITS.
     297     * @retval  VERR_RESOURCE_BUSY if another thread already made a waiting call.
     298     * @retval  VERR_INVALID_HANDLE if invalid client ID.
     299     * @retval  VERR_INVALID_PARAMETER if incorrect parameter count or types.
     300     * @note    This replaces GUEST_MSG_WAIT.
     301     * @since   6.0
     302     */
     303    GUEST_MSG_PEEK_WAIT,
     304    /** Gets the next message, returning immediately.
     305     *
     306     * First argument is the message ID returned by the peek and which the caller
     307     * expects to retrieve (holds actual message ID when VERR_MISMATCH is returned).
     308     * Second argument is the parameter count (output only) and exist for
     309     * compatibility with GUEST_MSG_WAIT.  Any subsequent parameters are specific to
     310     * the message being retrieved.
     311     *
     312     * @retval  VINF_SUCCESS if message retrieved and removed from the pending queue.
     313     * @retval  VERR_TRY_AGAIN if no message pending.
     314     * @retval  VERR_MISMATCH if the incoming message ID does not match the pending.
     315     * @retval  VERR_OUT_OF_RANGE if the wrong parameter count.
     316     * @retval  VERR_WRONG_TYPE if a parameter has the wrong type.
     317     * @retval  VERR_BUFFER_OVERFLOW if a parmeter buffer is too small.  The buffer
     318     *          size was updated to reflect the required size.
     319     * @retval  VERR_INVALID_HANDLE if invalid client ID.
     320     * @note    This replaces GUEST_MSG_WAIT.
     321     * @since   6.0
     322     */
     323    GUEST_MSG_GET,
     324    /** Cancels pending calls for this client session.
     325     *
     326     * This should be used if a GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT call gets
     327     * interrupted on the client end, so as to prevent being rebuffed with
     328     * VERR_RESOURCE_BUSY when restarting the call.
     329     *
     330     * @retval  VINF_SUCCESS if cancelled any calls.
     331     * @retval  VWRN_NOT_FOUND if no callers.
     332     * @retval  VERR_INVALID_PARAMETER if any parameters specified (expects zero).
     333     * @retval  VERR_INVALID_HANDLE if invalid client ID.
     334     * @since   6.0
     335     */
     336    GUEST_MSG_CANCEL,
     337
    265338    /**
    266339     * Guest reports back a guest session status.
     
    271344     */
    272345    GUEST_SESSION_CLOSE = 21,
     346
    273347    /**
    274348     * Guests sends output from an executed process.
  • trunk/src/VBox/HostServices/GuestControl/service.cpp

    r75750 r75755  
    6767
    6868#include <VBox/log.h>
     69#include <VBox/AssertGuest.h>
    6970#include <iprt/assert.h>
    7071#include <iprt/cpp/autores.h>
     
    472473          mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0),
    473474          mHostCmdTS(0),
    474           mIsPending(false),
    475           mPeekCount(0) { }
     475          mIsPending((guestControl::eGuestFn)0),
     476          mPeekCount(0)
     477    { }
    476478
    477479    ClientState(PVBOXHGCMSVCHELPERS pSvcHelpers, uint32_t uClientID)
     
    482484          mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0),
    483485          mHostCmdTS(0),
    484           mIsPending(false),
    485           mPeekCount(0){ }
     486          mIsPending((guestControl::eGuestFn)0),
     487          mPeekCount(0)
     488    { }
    486489
    487490    void DequeueAll(void)
     
    541544    }
    542545
     546#if 0 /* not used by anyone */
    543547    /** Returns the pointer to the current host command in a client's list.
    544548     *  NULL if no current command available. */
     
    550554        return (*mHostCmdList.begin());
    551555    }
     556#endif
    552557
    553558    bool WantsHostCommand(const HostCommand *pHostCmd) const
     
    587592    /**
    588593     * Set to indicate that a client call (GUEST_MSG_WAIT) is pending.
    589      */
    590     int SetPending(const ClientConnection *pConnection)
     594     *
     595     * @note Only used by GUEST_MSG_WAIT scenarios.
     596     */
     597    int OldSetPending(const ClientConnection *pConnection)
    591598    {
    592599        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
    593600
    594         if (mIsPending)
     601        if (mIsPending != 0)
    595602        {
    596603            LogFlowFunc(("[Client %RU32] Already is in pending mode\n", mID));
     
    604611        if (mHostCmdList.empty())
    605612        {
    606             AssertMsg(mIsPending == false,
    607                       ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID));
     613            AssertMsg(mIsPending == 0, ("Client ID=%RU32 already is pending but tried to receive a new host command\n", mID));
    608614
    609615            mPendingCon.mHandle   = pConnection->mHandle;
     
    611617            mPendingCon.mParms    = pConnection->mParms;
    612618
    613             mIsPending = true;
     619            mIsPending = GUEST_MSG_WAIT;
    614620
    615621            LogFlowFunc(("[Client %RU32] Is now in pending mode\n", mID));
     
    629635    }
    630636
    631     /** Used by Wakeup() and RunCurrent(). */
    632     int Run(ClientConnection const *pConnection,
    633             HostCommand            *pHostCmd)
     637    /**
     638     * Used by Wakeup() and OldRunCurrent().
     639     *
     640     * @note Only used by GUEST_MSG_WAIT scenarios.
     641     */
     642    int OldRun(ClientConnection const *pConnection,
     643               HostCommand            *pHostCmd)
    634644    {
    635645        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
     
    639649                      mID, pConnection, mHostCmdRc, mHostCmdTries, mPeekCount));
    640650
    641         int rc = mHostCmdRc = SendReply(pConnection, pHostCmd);
     651        int rc = mHostCmdRc = OldSendReply(pConnection, pHostCmd);
    642652
    643653        LogFlowThisFunc(("[Client %RU32] Processing command %RU32 ended with rc=%Rrc\n", mID, pHostCmd->mMsgType, mHostCmdRc));
     
    699709    }
    700710
    701     int RunCurrent(const ClientConnection *pConnection)
     711    /**
     712     * @note Only used by GUEST_MSG_WAIT scenarios.
     713     */
     714    int OldRunCurrent(const ClientConnection *pConnection)
    702715    {
    703716        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
     
    706719        if (mHostCmdList.empty())
    707720        {
    708             rc = SetPending(pConnection);
     721            rc = OldSetPending(pConnection);
    709722        }
    710723        else
    711724        {
    712             AssertMsgReturn(!mIsPending,
     725            AssertMsgReturn(mIsPending == 0,
    713726                            ("Client ID=%RU32 still is in pending mode; can't use another connection\n", mID), VERR_INVALID_PARAMETER);
    714727
     
    718731            AssertPtrReturn(pHostCmd, VERR_INVALID_POINTER);
    719732
    720             rc = Run(pConnection, pHostCmd);
     733            rc = OldRun(pConnection, pHostCmd);
    721734        }
    722735
     
    724737    }
    725738
    726     /** Used by for Service::hostProcessCommand(). */
     739    /**
     740     * Used by for Service::hostProcessCommand().
     741     *
     742     * @note This wakes up both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
     743     */
    727744    int Wakeup(void)
    728745    {
    729746        int rc = VINF_NO_CHANGE;
    730747
    731         if (mIsPending)
     748        if (mIsPending != 0)
    732749        {
    733750            LogFlowFunc(("[Client %RU32] Waking up ...\n", mID));
     
    744761                                 mID, pHostCmd->mMsgType, pHostCmd->mContextID, pHostCmd->mParmCount, pHostCmd->mRefCount));
    745762
    746                 rc = Run(&mPendingCon, pHostCmd);
     763                if (mIsPending == GUEST_MSG_PEEK_WAIT)
     764                {
     765                    HGCMSvcSetU32(&mPendingCon.mParms[0], pHostCmd->mMsgType);
     766                    HGCMSvcSetU32(&mPendingCon.mParms[1], pHostCmd->mParmCount);
     767                    for (uint32_t i = pHostCmd->mParmCount; i >= 2; i--)
     768                        switch (pHostCmd->mpParms[i].type)
     769                        {
     770                            case VBOX_HGCM_SVC_PARM_32BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
     771                            case VBOX_HGCM_SVC_PARM_64BIT: mPendingCon.mParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
     772                            case VBOX_HGCM_SVC_PARM_PTR:   mPendingCon.mParms[i].u.uint32 = pHostCmd->mpParms[i].u.pointer.size; break;
     773                        }
     774
     775                    rc = mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, VINF_SUCCESS);
     776                    mIsPending = (guestControl::eGuestFn)0;
     777                }
     778                else if (mIsPending == GUEST_MSG_WAIT)
     779                    rc = OldRun(&mPendingCon, pHostCmd);
     780                else
     781                    AssertMsgFailed(("mIsPending=%d\n", mIsPending));
    747782            }
    748783            else
     
    755790    }
    756791
    757     int CancelWaiting(int rcPending)
    758     {
    759         LogFlowFunc(("[Client %RU32] Cancelling waiting with %Rrc, isPending=%RTbool, pendingNumParms=%RU32, flags=%x\n",
    760                      mID, rcPending, mIsPending, mPendingCon.mNumParms, mFlags));
     792    /**
     793     * Used by Service::call() to handle GUEST_CANCEL_PENDING_WAITS.
     794     *
     795     * @note This cancels both GUEST_MSG_WAIT and GUEST_MSG_PEEK_WAIT sleepers.
     796     */
     797    int CancelWaiting()
     798    {
     799        LogFlowFunc(("[Client %RU32] Cancelling waiting thread, isPending=%d, pendingNumParms=%RU32, flags=%x\n",
     800                     mID, mIsPending, mPendingCon.mNumParms, mFlags));
    761801
    762802        int rc;
    763         if (   mIsPending
     803        if (   mIsPending != 0
    764804            && mPendingCon.mNumParms >= 2)
    765805        {
     
    768808
    769809            AssertPtr(mSvcHelpers);
    770             mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, rcPending);
    771 
    772             mIsPending = false;
     810            mSvcHelpers->pfnCallComplete(mPendingCon.mHandle, mIsPending == GUEST_MSG_WAIT ? VINF_SUCCESS : VINF_TRY_AGAIN);
     811
     812            mIsPending = (guestControl::eGuestFn)0;
    773813
    774814            rc = VINF_SUCCESS;
     
    782822    }
    783823
    784     /** Internal worker for Run(). */
    785     int SendReply(ClientConnection const *pConnection,
    786                   HostCommand            *pHostCmd)
     824    /**
     825     * Internal worker for OldRun().
     826     * @note Only used for GUEST_MSG_WAIT.
     827     */
     828    int OldSendReply(ClientConnection const *pConnection,
     829                     HostCommand            *pHostCmd)
    787830    {
    788831        AssertPtrReturn(pConnection, VERR_INVALID_POINTER);
     
    797840        if (mIsPending)
    798841        {
     842            Assert(mIsPending == GUEST_MSG_WAIT);
    799843            rc = pHostCmd->Peek(pConnection);
    800844            mPeekCount++;
     
    826870
    827871        /* Reset pending status. */
    828         mIsPending = false;
     872        mIsPending = (guestControl::eGuestFn)0;
    829873
    830874        /* In any case the client did something, so complete
     
    866910     * @todo r=bird: Where is this set?  */
    867911    uint64_t mHostCmdTS;
    868     /** Flag indicating whether a client call (GUEST_MSG_WAIT) currently is pending.
     912    /** Pending client call (GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT), zero if none pending.
    869913     *
    870914     * This means the client waits for a new host command to reply and won't return
    871915     * from the waiting call until a new host command is available.
    872916     */
    873     bool mIsPending;
     917    guestControl::eGuestFn mIsPending;
    874918    /** Number of times we've peeked at a pending message.
    875919     *
     
    10191063    int clientConnect(uint32_t u32ClientID, void *pvClient);
    10201064    int clientDisconnect(uint32_t u32ClientID, void *pvClient);
     1065    int clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     1066    int clientMsgPeek(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait);
    10211067    int clientMsgGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     1068    int clientMsgCancel(uint32_t u32ClientID, uint32_t cParms);
    10221069    int clientMsgFilterSet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
    10231070    int clientMsgFilterUnset(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     
    11501197 * @param   paParms                     Array of parameters.
    11511198 */
    1152 int Service::clientMsgGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle,
    1153                           uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1199int Service::clientMsgOldGet(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle,
     1200                             uint32_t cParms, VBOXHGCMSVCPARM paParms[])
    11541201{
    11551202    /*
     
    11771224    thisCon.mParms    = paParms;
    11781225
    1179     return clientState.RunCurrent(&thisCon);
     1226    return clientState.OldRunCurrent(&thisCon);
    11801227}
     1228
     1229/**
     1230 * Implements GUEST_MSG_PEEK_WAIT and GUEST_MSG_PEEK_NOWAIT.
     1231 *
     1232 * @returns VBox status code.
     1233 * @retval  VINF_SUCCESS if a message was pending and is being returned.
     1234 * @retval  VERR_INVALID_HANDLE if invalid client ID.
     1235 * @retval  VERR_INVALID_PARAMETER if incorrect parameter count or types.
     1236 * @retval  VERR_TRY_AGAIN if no message pending and not blocking.
     1237 * @retval  VERR_RESOURCE_BUSY if another read already made a waiting call.
     1238 * @retval  VINF_HGCM_ASYNC_EXECUTE if message wait is pending.
     1239 *
     1240 * @param   idClientID  The client's ID.
     1241 * @param   hCall       The client's call handle.
     1242 * @param   cParms      Number of parameters.
     1243 * @param   paParms     Array of parameters.
     1244 * @param   fWait       Set if we should wait for a message, clear if to return
     1245 *                      immediately.
     1246 */
     1247int Service::clientMsgPeek(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait)
     1248{
     1249    /*
     1250     * Validate the request.
     1251     */
     1252    ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER);
     1253    for (uint32_t i = 0; i < cParms; i++)
     1254    {
     1255        ASSERT_GUEST_MSG_RETURN(paParms[i].type == VBOX_HGCM_SVC_PARM_32BIT, ("#%u type=%u\n", i, paParms[i].type),
     1256                                VERR_INVALID_PARAMETER);
     1257        paParms[i].u.uint32 = 0;
     1258    }
     1259
     1260    ClientStateMapIter itClientState = mClientStateMap.find(idClient);
     1261    ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE);
     1262
     1263    ClientState &rClientState = itClientState->second;
     1264
     1265    /*
     1266     * Return information about the first command if one is pending in the list.
     1267     */
     1268    HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin();
     1269    if (itFirstCmd != rClientState.mHostCmdList.end())
     1270    {
     1271        HostCommand *pFirstCmd = *itFirstCmd;
     1272        paParms[0].u.uint32 = pFirstCmd->mMsgType;
     1273        paParms[1].u.uint32 = pFirstCmd->mParmCount;
     1274        for (uint32_t i = pFirstCmd->mParmCount; i >= 2; i--)
     1275            switch (pFirstCmd->mpParms[i].type)
     1276            {
     1277                case VBOX_HGCM_SVC_PARM_32BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
     1278                case VBOX_HGCM_SVC_PARM_64BIT: paParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
     1279                case VBOX_HGCM_SVC_PARM_PTR:   paParms[i].u.uint32 = pFirstCmd->mpParms[i].u.pointer.size; break;
     1280            }
     1281
     1282        LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_XXXX -> VINF_SUCCESS (idMsg=%u, cParms=%u)\n",
     1283                     idClient, pFirstCmd->mMsgType, pFirstCmd->mParmCount));
     1284        return VINF_SUCCESS;
     1285    }
     1286
     1287    /*
     1288     * If we cannot wait, fail the call.
     1289     */
     1290    if (!fWait)
     1291    {
     1292        LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", idClient));
     1293        return VERR_TRY_AGAIN;
     1294    }
     1295
     1296    /*
     1297     * Wait for the host to queue a message for this client.
     1298     */
     1299    ASSERT_GUEST_MSG_RETURN(rClientState.mIsPending == 0, ("Already pending! (idClient=%RU32)\n", idClient), VERR_RESOURCE_BUSY);
     1300    rClientState.mPendingCon.mHandle    = hCall;
     1301    rClientState.mPendingCon.mNumParms  = cParms;
     1302    rClientState.mPendingCon.mParms     = paParms;
     1303    rClientState.mIsPending             = GUEST_MSG_PEEK_WAIT;
     1304    LogFlowFunc(("[Client %RU32] Is now in pending mode\n", idClient));
     1305    return VINF_HGCM_ASYNC_EXECUTE;
     1306}
     1307
     1308/**
     1309 * Implements GUEST_MSG_GET.
     1310 *
     1311 * @returns VBox status code.
     1312 * @retval  VINF_SUCCESS if message retrieved and removed from the pending queue.
     1313 * @retval  VERR_TRY_AGAIN if no message pending.
     1314 * @retval  VERR_BUFFER_OVERFLOW if a parmeter buffer is too small.  The buffer
     1315 *          size was updated to reflect the required size.
     1316 * @retval  VERR_MISMATCH if the incoming message ID does not match the pending.
     1317 * @retval  VERR_OUT_OF_RANGE if the wrong parameter count.
     1318 * @retval  VERR_WRONG_TYPE if a parameter has the wrong type.
     1319 * @retval  VERR_INVALID_HANDLE if invalid client ID.
     1320 * @retval  VINF_HGCM_ASYNC_EXECUTE if message wait is pending.
     1321 *
     1322 * @param   idClientID  The client's ID.
     1323 * @param   hCall       The client's call handle.
     1324 * @param   cParms      Number of parameters.
     1325 * @param   paParms     Array of parameters.
     1326 */
     1327int Service::clientMsgGet(uint32_t idClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
     1328{
     1329    /*
     1330     * Validate the request.
     1331     *
     1332     * Note! The 2nd parameter is basically ignored as it's only purpose is
     1333     *       compatibility with GUEST_MSG_WAIT
     1334     */
     1335    ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER);
     1336    ASSERT_GUEST_MSG_RETURN(paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT, ("type=%u\n", paParms[0].type), VERR_WRONG_TYPE);
     1337    uint32_t const idMsgExpected  = paParms[0].u.uint32;
     1338    ASSERT_GUEST_MSG_RETURN(paParms[1].type == VBOX_HGCM_SVC_PARM_32BIT, ("type=%u\n", paParms[0].type), VERR_WRONG_TYPE);
     1339
     1340    ClientStateMapIter itClientState = mClientStateMap.find(idClient);
     1341    ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE);
     1342
     1343    ClientState &rClientState = itClientState->second;
     1344
     1345    /*
     1346     * Return information aobut the first command if one is pending in the list.
     1347     */
     1348    HostCmdListIter itFirstCmd = rClientState.mHostCmdList.begin();
     1349    if (itFirstCmd != rClientState.mHostCmdList.end())
     1350    {
     1351        HostCommand *pFirstCmd = *itFirstCmd;
     1352
     1353        /* The 'peek' parameters. */
     1354        paParms[0].u.uint32 = pFirstCmd->mMsgType;
     1355        paParms[1].u.uint32 = pFirstCmd->mParmCount;
     1356        ASSERT_GUEST_MSG_RETURN(pFirstCmd->mMsgType == idMsgExpected,
     1357                                ("idMsg=%u cParms=%u, caller expected %u and %u\n",
     1358                                 pFirstCmd->mMsgType, pFirstCmd->mParmCount, idMsgExpected, cParms),
     1359                                VERR_MISMATCH);
     1360        ASSERT_GUEST_MSG_RETURN(pFirstCmd->mParmCount == cParms,
     1361                                ("idMsg=%u cParms=%u, caller expected %u and %u\n",
     1362                                 pFirstCmd->mMsgType, pFirstCmd->mParmCount, idMsgExpected, cParms),
     1363                                VERR_OUT_OF_RANGE);
     1364
     1365        /* Check the parameter types. */
     1366        for (uint32_t i = 2; i < cParms; i++)
     1367            ASSERT_GUEST_MSG_RETURN(pFirstCmd->mpParms[i].type == paParms[i].type,
     1368                                    ("param #%u: type %u, caller expected %u\n", i, pFirstCmd->mpParms[i].type, paParms[i].type),
     1369                                    VERR_WRONG_TYPE);
     1370
     1371        /*
     1372         * Copy out the parameters.
     1373         *
     1374         * No assertions on buffer overflows, and keep going till the end so we can
     1375         * communicate all the required buffer sizes.
     1376         */
     1377        int rc = VINF_SUCCESS;
     1378        for (uint32_t i = 2; i < cParms; i++)
     1379            switch (pFirstCmd->mpParms[i].type)
     1380            {
     1381                case VBOX_HGCM_SVC_PARM_32BIT:
     1382                    paParms[i].u.uint32 = pFirstCmd->mpParms[i].u.uint32;
     1383                    break;
     1384
     1385                case VBOX_HGCM_SVC_PARM_64BIT:
     1386                    paParms[i].u.uint64 = pFirstCmd->mpParms[i].u.uint64;
     1387                    break;
     1388
     1389                case VBOX_HGCM_SVC_PARM_PTR:
     1390                {
     1391                    uint32_t const cbSrc = pFirstCmd->mpParms[i].u.pointer.size;
     1392                    uint32_t const cbDst = paParms[i].u.pointer.size;
     1393                    paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
     1394                                                        * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
     1395                    if (cbSrc <= cbDst)
     1396                        memcpy(paParms[i].u.pointer.addr, pFirstCmd->mpParms[i].u.pointer.addr, cbSrc);
     1397                    else
     1398                        rc = VERR_BUFFER_OVERFLOW;
     1399                    break;
     1400                }
     1401
     1402                default:
     1403                    AssertMsgFailed(("#%u: %u\n", i, pFirstCmd->mpParms[i].type));
     1404                    rc = VERR_INTERNAL_ERROR;
     1405                    break;
     1406            }
     1407        if (RT_SUCCESS(rc))
     1408        {
     1409            /*
     1410             * Complete the command and remove the pending message unless the
     1411             * guest raced us and cancelled this call in the meantime.
     1412             */
     1413            AssertPtr(mpHelpers);
     1414            rc = mpHelpers->pfnCallComplete(hCall, rc);
     1415            if (rc != VERR_CANCELLED)
     1416            {
     1417                rClientState.mHostCmdList.erase(itFirstCmd);
     1418                if (pFirstCmd->Release() == 0)
     1419                {
     1420                    delete pFirstCmd;
     1421                    LogFlow(("[Client %RU32] Destroying command (idMsg=%u cParms=%u)\n", idClient, idMsgExpected, cParms));
     1422                }
     1423            }
     1424            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
     1425        }
     1426        return rc;
     1427    }
     1428
     1429    paParms[0].u.uint32 = 0;
     1430    paParms[1].u.uint32 = 0;
     1431    LogFlowFunc(("[Client %RU32] GUEST_MSG_GET -> VERR_TRY_AGAIN\n", idClient));
     1432    return VERR_TRY_AGAIN;
     1433}
     1434
     1435/**
     1436 * Implements GUEST_MSG_CANCEL.
     1437 *
     1438 * @returns VBox status code.
     1439 * @retval  VINF_SUCCESS if cancelled any calls.
     1440 * @retval  VWRN_NOT_FOUND if no callers.
     1441 * @retval  VERR_INVALID_PARAMETER if any parameters specified (expects zero).
     1442 * @retval  VERR_INVALID_HANDLE if invalid client ID.
     1443 * @retval  VINF_HGCM_ASYNC_EXECUTE if message wait is pending.
     1444 *
     1445 * @param   idClientID  The client's ID.
     1446 * @param   cParms      Number of parameters.
     1447 */
     1448int Service::clientMsgCancel(uint32_t idClient, uint32_t cParms)
     1449{
     1450    /*
     1451     * Validate the request.
     1452     */
     1453    ASSERT_GUEST_MSG_RETURN(cParms == 0, ("cParms=%u!\n", cParms), VERR_INVALID_PARAMETER);
     1454
     1455    ClientStateMapIter itClientState = mClientStateMap.find(idClient);
     1456    ASSERT_GUEST_MSG_RETURN(itClientState != mClientStateMap.end(), ("idClient=%RU32\n", idClient), VERR_INVALID_HANDLE);
     1457
     1458    ClientState &rClientState = itClientState->second;
     1459    if (rClientState.mIsPending != 0)
     1460    {
     1461        rClientState.CancelWaiting();
     1462        return VINF_SUCCESS;
     1463    }
     1464    return VWRN_NOT_FOUND;
     1465}
     1466
    11811467
    11821468/**
     
    14471733        if (eFunction == GUEST_MSG_WAIT)
    14481734        {
    1449             LogFlowFunc(("[Client %RU32] GUEST_MSG_GET\n", u32ClientID));
    1450             rc = clientMsgGet(u32ClientID, callHandle, cParms, paParms);
     1735            LogFlowFunc(("[Client %RU32] GUEST_MSG_WAIT\n", u32ClientID));
     1736            rc = clientMsgOldGet(u32ClientID, callHandle, cParms, paParms);
    14511737        }
    14521738        else
     
    14641750                    ClientStateMapIter itClientState = mClientStateMap.find(u32ClientID);
    14651751                    if (itClientState != mClientStateMap.end())
    1466                         rc = itClientState->second.CancelWaiting(VINF_SUCCESS /* Pending result */);
     1752                        rc = itClientState->second.CancelWaiting();
    14671753                    break;
    14681754                }
     
    14971783
    14981784                /*
     1785                 * New message peeking and retrieval functions replacing GUEST_MSG_WAIT.
     1786                 */
     1787                case GUEST_MSG_PEEK_NOWAIT:
     1788                    LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT\n", u32ClientID));
     1789                    rc = clientMsgPeek(u32ClientID, callHandle, cParms, paParms, false /*fWait*/);
     1790                    break;
     1791                case GUEST_MSG_PEEK_WAIT:
     1792                    LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_WAIT\n", u32ClientID));
     1793                    rc = clientMsgPeek(u32ClientID, callHandle, cParms, paParms, true /*fWait*/);
     1794                    break;
     1795                case GUEST_MSG_GET:
     1796                    LogFlowFunc(("[Client %RU32] GUEST_MSG_GET\n", u32ClientID));
     1797                    rc = clientMsgGet(u32ClientID, callHandle, cParms, paParms);
     1798                    break;
     1799                case GUEST_MSG_CANCEL:
     1800                    LogFlowFunc(("[Client %RU32] GUEST_MSG_CANCEL\n", u32ClientID));
     1801                    rc = clientMsgCancel(u32ClientID, cParms);
     1802                    break;
     1803
     1804                /*
    14991805                 * The guest wants to close specific guest session. This is handy for
    15001806                 * shutting down dedicated guest session processes from another process.
     
    15521858                while (itClientState != mClientStateMap.end())
    15531859                {
    1554                     int rc2 = itClientState->second.CancelWaiting(VINF_SUCCESS /* Pending rc. */);
     1860                    int rc2 = itClientState->second.CancelWaiting();
    15551861                    if (RT_FAILURE(rc2))
    15561862                        LogFlowFunc(("Cancelling waiting for client ID=%RU32 failed with rc=%Rrc",
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