Exemplo n.º 1
0
/* static */
DECLCALLBACK(int) Guest::notifyCtrlDispatcher(void    *pvExtension,
                                              uint32_t u32Function,
                                              void    *pvParms,
                                              uint32_t cbParms)
{
    using namespace guestControl;

    /*
     * No locking, as this is purely a notification which does not make any
     * changes to the object state.
     */
    LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
                 pvExtension, u32Function, pvParms, cbParms));
    ComObjPtr<Guest> pGuest = reinterpret_cast<Guest *>(pvExtension);
    Assert(!pGuest.isNull());

    /*
     * For guest control 2.0 using the legacy commands we need to do the following here:
     * - Get the callback header to access the context ID
     * - Get the context ID of the callback
     * - Extract the session ID out of the context ID
     * - Dispatch the whole stuff to the appropriate session (if still exists)
     */

    PCALLBACKHEADER pHeader = (PCALLBACKHEADER)pvParms;
    AssertPtr(pHeader);

#ifdef DEBUG
    LogFlowFunc(("CID=%RU32, uSession=%RU32, uObject=%RU32, uCount=%RU32\n",
                 pHeader->u32ContextID,
                 VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pHeader->u32ContextID),
                 VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(pHeader->u32ContextID),
                 VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(pHeader->u32ContextID)));
#endif

    bool fDispatch = true;
#ifdef DEBUG
    /*
     * Pre-check: If we got a status message with an error and VERR_TOO_MUCH_DATA
     *            it means that that guest could not handle the entire message
     *            because of its exceeding size. This should not happen on daily
     *            use but testcases might try this. It then makes no sense to dispatch
     *            this further because we don't have a valid context ID.
     */
    if (u32Function == GUEST_EXEC_SEND_STATUS)
    {
        PCALLBACKDATAEXECSTATUS pCallbackData = reinterpret_cast<PCALLBACKDATAEXECSTATUS>(pvParms);
        AssertPtr(pCallbackData);
        AssertReturn(sizeof(CALLBACKDATAEXECSTATUS) == cbParms, VERR_INVALID_PARAMETER);
        AssertReturn(CALLBACKDATAMAGIC_EXEC_STATUS == pCallbackData->hdr.u32Magic, VERR_INVALID_PARAMETER);

        if (   pCallbackData->u32Status == PROC_STS_ERROR
            && ((int)pCallbackData->u32Flags)  == VERR_TOO_MUCH_DATA)
        {
            LogFlowFunc(("Requested command with too much data, skipping dispatching ...\n"));

            Assert(pCallbackData->u32PID == 0);
            fDispatch = false;
        }
    }
#endif
    int rc = VINF_SUCCESS;
    if (fDispatch)
    {
        rc = pGuest->dispatchToSession(pHeader->u32ContextID, u32Function, pvParms, cbParms);
        if (RT_SUCCESS(rc))
            return rc;
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}