Exemple #1
0
STDMETHODIMP EventSource::EventProcessed(IEventListener * aListener,
                                         IEvent *         aEvent)
{
    CheckComArgNotNull(aListener);
    CheckComArgNotNull(aEvent);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    Listeners::iterator it = m->mListeners.find(aListener);
    HRESULT rc;

    BOOL aWaitable = FALSE;
    aEvent->COMGETTER(Waitable)(&aWaitable);

    if (it != m->mListeners.end())
    {
        ListenerRecord* aRecord = it->second.obj();

        if (aRecord->isActive())
            return setError(E_INVALIDARG,
                        tr("Only applicable to passive listeners"));

        if (aWaitable)
        {
            PendingEventsMap::iterator pit = m->mPendingMap.find(aEvent);

            if (pit == m->mPendingMap.end())
            {
                AssertFailed();
                rc = setError(VBOX_E_OBJECT_NOT_FOUND,
                              tr("Unknown event"));
            }
            else
                rc = aRecord->eventProcessed(aEvent, pit);
        }
        else
        {
            // for non-waitable events we're done
            rc = S_OK;
        }
    }
    else
    {
        rc = setError(VBOX_E_OBJECT_NOT_FOUND,
                      tr("Listener was never registered"));
    }

    return rc;
}
Exemple #2
0
STDMETHODIMP EventSource::GetEvent(IEventListener * aListener,
                                   LONG             aTimeout,
                                   IEvent  **       aEvent)
{

    CheckComArgNotNull(aListener);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    Listeners::iterator it = m->mListeners.find(aListener);
    HRESULT rc;

    if (it != m->mListeners.end())
        rc = it->second.obj()->dequeue(aEvent, aTimeout, alock);
    else
        rc = setError(VBOX_E_OBJECT_NOT_FOUND,
                      tr("Listener was never registered"));

    if (rc == VBOX_E_INVALID_OBJECT_STATE)
        return setError(rc, tr("Listener must be passive"));

    return rc;
}
Exemple #3
0
STDMETHODIMP EventSource::RegisterListener(IEventListener * aListener,
                                           ComSafeArrayIn(VBoxEventType_T, aInterested),
                                           BOOL             aActive)
{
    CheckComArgNotNull(aListener);
    CheckComArgSafeArrayNotNull(aInterested);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    {
        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

        Listeners::const_iterator it = m->mListeners.find(aListener);
        if (it != m->mListeners.end())
            return setError(E_INVALIDARG,
                            tr("This listener already registered"));

        com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg (aInterested));
        RecordHolder<ListenerRecord> lrh(new ListenerRecord(aListener, interested, aActive, this));
        m->mListeners.insert(Listeners::value_type(aListener, lrh));
    }

    VBoxEventDesc evDesc;
    evDesc.init(this, VBoxEventType_OnEventSourceChanged, aListener, TRUE);
    evDesc.fire(0);

    return S_OK;
}
Exemple #4
0
STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment,
                                        ULONG aSourceIdx, ULONG aTargetIdx,
                                        IMedium *aSource, IMedium *aTarget,
                                        BOOL aMergeForward,
                                        IMedium *aParentForTarget,
                                        ComSafeArrayIn(IMedium *, aChildrenToReparent),
                                        IProgress *aProgress)
{
    AutoCaller autoCaller(this);
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());

    if (mState != SessionState_Locked)
        return setError(VBOX_E_INVALID_VM_STATE,
                        tr("Machine is not locked by session (session state: %s)."),
                        Global::stringifySessionState(mState));
    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    CheckComArgNotNull(aMediumAttachment);
    CheckComArgSafeArrayNotNull(aChildrenToReparent);

    return mConsole->onlineMergeMedium(aMediumAttachment, aSourceIdx,
                                       aTargetIdx, aSource, aTarget,
                                       aMergeForward, aParentForTarget,
                                       ComSafeArrayInArg(aChildrenToReparent),
                                       aProgress);
}
Exemple #5
0
STDMETHODIMP EventSource::UnregisterListener(IEventListener * aListener)
{
    CheckComArgNotNull(aListener);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    HRESULT rc;
    {
        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

        Listeners::iterator it = m->mListeners.find(aListener);

        if (it != m->mListeners.end())
        {
            m->mListeners.erase(it);
            // destructor removes refs from the event map
            rc = S_OK;
        }
        else
        {
            rc = setError(VBOX_E_OBJECT_NOT_FOUND,
                          tr("Listener was never registered"));
        }
    }

    if (SUCCEEDED(rc))
    {
        VBoxEventDesc evDesc;
        evDesc.init(this, VBoxEventType_OnEventSourceChanged, aListener, FALSE);
        evDesc.fire(0);
    }

    return rc;
}
Exemple #6
0
/**
 * Returns the status of a specified Guest Additions facility.
 *
 * @return  aStatus         Current status of specified facility.
 * @param   aType           Facility to get the status from.
 * @param   aTimestamp      Timestamp of last facility status update in ms (optional).
 */
STDMETHODIMP Guest::GetFacilityStatus(AdditionsFacilityType_T aType, LONG64 *aTimestamp, AdditionsFacilityStatus_T *aStatus)
{
    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    CheckComArgNotNull(aStatus);
    /* Not checking for aTimestamp is intentional; it's optional. */

    FacilityMapIterConst it = mData.mFacilityMap.find(aType);
    if (it != mData.mFacilityMap.end())
    {
        AdditionsFacility *pFacility = it->second;
        ComAssert(pFacility);
        *aStatus = pFacility->getStatus();
        if (aTimestamp)
            *aTimestamp = pFacility->getLastUpdated();
    }
    else
    {
        /*
         * Do not fail here -- could be that the facility never has been brought up (yet) but
         * the host wants to have its status anyway. So just tell we don't know at this point.
         */
        *aStatus = AdditionsFacilityStatus_Unknown;
        if (aTimestamp)
            *aTimestamp = RTTimeMilliTS();
    }
    return S_OK;
}
Exemple #7
0
STDMETHODIMP VBoxEvent::COMGETTER(Waitable)(BOOL *aWaitable)
{
    CheckComArgNotNull(aWaitable);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    // never  changes till event alive, no locking?
    *aWaitable = m->mWaitable;
    return S_OK;
}
Exemple #8
0
STDMETHODIMP VBoxEvent::COMGETTER(Type)(VBoxEventType_T *aType)
{
    CheckComArgNotNull(aType);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    // never  changes till event alive, no locking?
    *aType = m->mType;
    return S_OK;
}
Exemple #9
0
STDMETHODIMP
NATEngine::COMGETTER(Network)(BSTR *aNetwork)
{
    CheckComArgNotNull(aNetwork);
    AutoCaller autoCaller(this);
    AssertComRCReturnRC(autoCaller.rc());

    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    if (!mData->mNetwork.isEmpty())
    {
        mData->mNetwork.cloneTo(aNetwork);
        Log(("Getter (this:%p) Network: %s\n", this, mData->mNetwork.c_str()));
    }
    return S_OK;
}
Exemple #10
0
STDMETHODIMP VBoxEvent::WaitProcessed(LONG aTimeout, BOOL *aResult)
{
    CheckComArgNotNull(aResult);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    {
        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

        if (m->mProcessed)
        {
            *aResult = TRUE;
            return S_OK;
        }

        if (aTimeout == 0)
        {
            *aResult = m->mProcessed;
            return S_OK;
        }
    }

    /* @todo: maybe while loop for spurious wakeups? */
    int vrc = ::RTSemEventWait(m->mWaitEvent, aTimeout);
    AssertMsg(RT_SUCCESS(vrc) || vrc == VERR_TIMEOUT || vrc == VERR_INTERRUPTED,
              ("RTSemEventWait returned %Rrc\n", vrc));

    if (RT_SUCCESS(vrc))
    {
        AssertMsg(m->mProcessed,
                  ("mProcessed must be set here\n"));
        *aResult = m->mProcessed;
    }
    else
    {
        *aResult = FALSE;
    }

    return S_OK;
}
/**
 * Checks a Machine object for any pending errors.
 *
 * @returns COM status code
 * @param   aMachine    Machine object to check.
 */
STDMETHODIMP VirtualBoxClient::CheckMachineError(IMachine *aMachine)
{
    HRESULT rc;
    CheckComArgNotNull(aMachine);

    BOOL fAccessible = FALSE;
    rc = aMachine->COMGETTER(Accessible)(&fAccessible);
    if (FAILED(rc))
        return setError(rc, tr("Could not check the accessibility status of the VM"));
    else if (!fAccessible)
    {
        ComPtr<IVirtualBoxErrorInfo> pAccessError;
        rc = aMachine->COMGETTER(AccessError)(pAccessError.asOutParam());
        if (FAILED(rc))
            return setError(rc, tr("Could not get the access error message of the VM"));
        else
        {
            ErrorInfo info(pAccessError);
            ErrorInfoKeeper eik(info);
            return info.getResultCode();
        }
    }
    return S_OK;
}
STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment,
                                        ULONG aSourceIdx, ULONG aTargetIdx,
                                        IProgress *aProgress)
{
    AutoCaller autoCaller(this);
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());

    if (mState != SessionState_Locked)
        return setError(VBOX_E_INVALID_VM_STATE,
                        tr("Machine is not locked by session (session state: %s)."),
                        Global::stringifySessionState(mState));
#ifndef VBOX_COM_INPROC_API_CLIENT
    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    CheckComArgNotNull(aMediumAttachment);

    return mConsole->onlineMergeMedium(aMediumAttachment,
                                       aSourceIdx, aTargetIdx,
                                       aProgress);
#else
    AssertFailed();
    return E_NOTIMPL;
#endif
}
STDMETHODIMP SystemProperties::COMSETTER(DefaultVRDEExtPack)(IN_BSTR aExtPack)
{
    CheckComArgNotNull(aExtPack);
    Utf8Str strExtPack(aExtPack);

    AutoCaller autoCaller(this);
    HRESULT hrc = autoCaller.rc();
    if (SUCCEEDED(hrc))
    {
        if (strExtPack.isNotEmpty())
        {
            if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
                hrc = S_OK;
            else
#ifdef VBOX_WITH_EXTPACK
                hrc = mParent->getExtPackManager()->checkVrdeExtPack(&strExtPack);
#else
                hrc = setError(E_FAIL, tr("The extension pack '%s' does not exist"), strExtPack.c_str());
#endif
        }
        if (SUCCEEDED(hrc))
        {
            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
            hrc = setDefaultVRDEExtPack(aExtPack);
            if (SUCCEEDED(hrc))
            {
                /* VirtualBox::saveSettings() needs the VirtualBox write lock. */
                alock.release();
                AutoWriteLock vboxLock(mParent COMMA_LOCKVAL_SRC_POS);
                hrc = mParent->saveSettings();
            }
        }
    }

    return hrc;
}
STDMETHODIMP MachineDebugger::COMGETTER(OSVersion)(BSTR *a_pbstrVersion)
{
    LogFlowThisFunc(("\n"));
    CheckComArgNotNull(a_pbstrVersion);
    AutoCaller autoCaller(this);
    HRESULT hrc = autoCaller.rc();
    if (SUCCEEDED(hrc))
    {
        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
        Console::SafeVMPtr ptrVM(mParent);
        hrc = ptrVM.rc();
        if (SUCCEEDED(hrc))
        {
            /*
             * Do the job and try convert the name.
             */
            char szVersion[256];
            int vrc = DBGFR3OSQueryNameAndVersion(ptrVM.raw(), NULL, 0, szVersion, sizeof(szVersion));
            if (RT_SUCCESS(vrc))
            {
                try
                {
                    Bstr bstrVersion(szVersion);
                    bstrVersion.detachTo(a_pbstrVersion);
                }
                catch (std::bad_alloc)
                {
                    hrc = E_OUTOFMEMORY;
                }
            }
            else
                hrc = setError(VBOX_E_VM_ERROR, tr("DBGFR3OSQueryNameAndVersion failed with %Rrc"), vrc);
        }
    }
    return hrc;
}
STDMETHODIMP USBController::InsertDeviceFilter(ULONG aPosition,
                                               IUSBDeviceFilter *aFilter)
{
#ifdef VBOX_WITH_USB

    CheckComArgNotNull(aFilter);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /* the machine needs to be mutable */
    AutoMutableStateDependency adep(m->pParent);
    if (FAILED(adep.rc())) return adep.rc();

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    ComObjPtr<USBDeviceFilter> filter = static_cast<USBDeviceFilter*>(aFilter);
    // @todo r=dj make sure the input object is actually from us
//     if (!filter)
//         return setError (E_INVALIDARG,
//             tr ("The given USB device filter is not created within "
//                 "this VirtualBox instance"));

    if (filter->mInList)
        return setError(VBOX_E_INVALID_OBJECT_STATE,
                        tr("The given USB device filter is already in the list"));

    /* backup the list before modification */
    m->llDeviceFilters.backup();

    /* iterate to the position... */
    DeviceFilterList::iterator it;
    if (aPosition < m->llDeviceFilters->size())
    {
        it = m->llDeviceFilters->begin();
        std::advance (it, aPosition);
    }
    else
        it = m->llDeviceFilters->end();
    /* ...and insert */
    m->llDeviceFilters->insert (it, filter);
    filter->mInList = true;

    /* notify the proxy (only when it makes sense) */
    if (filter->getData().mActive && Global::IsOnline(adep.machineState())
        && filter->getData().mRemote.isMatch (false))
    {
        USBProxyService *service = m->pHost->usbProxyService();
        ComAssertRet(service, E_FAIL);

        ComAssertRet(filter->getId() == NULL, E_FAIL);
        filter->getId() = service->insertFilter (&filter->getData().mUSBFilter);
    }

    alock.release();
    AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS);
    m->pParent->setModified(Machine::IsModified_USB);
    mlock.release();

    return S_OK;

#else /* VBOX_WITH_USB */

    NOREF(aPosition);
    NOREF(aFilter);
    ReturnComNotImplemented();

#endif /* VBOX_WITH_USB */
}
Exemple #16
0
STDMETHODIMP Progress::WaitForAsyncProgressCompletion(IProgress *pProgressAsync)
{
    LogFlowThisFuncEnter();

    CheckComArgNotNull(pProgressAsync);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /* Note: we don't lock here, cause we just using public methods. */

    HRESULT rc           = S_OK;
    BOOL fCancelable     = FALSE;
    BOOL fCompleted      = FALSE;
    BOOL fCanceled       = FALSE;
    ULONG prevPercent    = UINT32_MAX;
    ULONG currentPercent = 0;
    ULONG cOp            = 0;
    /* Is the async process cancelable? */
    rc = pProgressAsync->COMGETTER(Cancelable)(&fCancelable);
    if (FAILED(rc)) return rc;
    /* Loop as long as the sync process isn't completed. */
    while (SUCCEEDED(pProgressAsync->COMGETTER(Completed(&fCompleted))))
    {
        /* We can forward any cancel request to the async process only when
         * it is cancelable. */
        if (fCancelable)
        {
            rc = COMGETTER(Canceled)(&fCanceled);
            if (FAILED(rc)) return rc;
            if (fCanceled)
            {
                rc = pProgressAsync->Cancel();
                if (FAILED(rc)) return rc;
            }
        }
        /* Even if the user canceled the process, we have to wait until the
           async task has finished his work (cleanup and such). Otherwise there
           will be sync trouble (still wrong state, dead locks, ...) on the
           used objects. So just do nothing, but wait for the complete
           notification. */
        if (!fCanceled)
        {
            /* Check if the current operation has changed. It is also possible that
             * in the meantime more than one async operation was finished. So we
             * have to loop as long as we reached the same operation count. */
            ULONG curOp;
            for (;;)
            {
                rc = pProgressAsync->COMGETTER(Operation(&curOp));
                if (FAILED(rc)) return rc;
                if (cOp != curOp)
                {
                    Bstr bstr;
                    ULONG currentWeight;
                    rc = pProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
                    if (FAILED(rc)) return rc;
                    rc = pProgressAsync->COMGETTER(OperationWeight(&currentWeight));
                    if (FAILED(rc)) return rc;
                    rc = SetNextOperation(bstr.raw(), currentWeight);
                    if (FAILED(rc)) return rc;
                    ++cOp;
                }
                else
                    break;
            }

            rc = pProgressAsync->COMGETTER(OperationPercent(&currentPercent));
            if (FAILED(rc)) return rc;
            if (currentPercent != prevPercent)
            {
                prevPercent = currentPercent;
                rc = SetCurrentOperationProgress(currentPercent);
                if (FAILED(rc)) return rc;
            }
        }
        if (fCompleted)
            break;

        /* Make sure the loop is not too tight */
        rc = pProgressAsync->WaitForCompletion(100);
        if (FAILED(rc)) return rc;
    }

    LogFlowThisFuncLeave();

    return rc;
}
Exemple #17
0
STDMETHODIMP EventSource::FireEvent(IEvent * aEvent,
                                    LONG     aTimeout,
                                    BOOL     *aProcessed)
{
    CheckComArgNotNull(aEvent);
    CheckComArgOutPointerValid(aProcessed);

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    HRESULT hrc;
    BOOL aWaitable = FALSE;
    aEvent->COMGETTER(Waitable)(&aWaitable);

    do {
        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

        VBoxEventType_T evType;
        hrc = aEvent->COMGETTER(Type)(&evType);
        AssertComRCReturn(hrc, hrc);

        EventMapList &listeners = m->mEvMap[(int)evType - FirstEvent];

        /* Anyone interested in this event? */
        uint32_t cListeners = listeners.size();
        if (cListeners == 0)
        {
            aEvent->SetProcessed();
            break; // just leave the lock and update event object state
        }

        PendingEventsMap::iterator pit;

        if (aWaitable)
        {
            m->mPendingMap.insert(PendingEventsMap::value_type(aEvent, cListeners));
            // we keep iterator here to allow processing active listeners without
            // pending events lookup
            pit = m->mPendingMap.find(aEvent);
        }
        for (EventMapList::iterator it = listeners.begin();
             it != listeners.end();
             ++it)
        {
            HRESULT cbRc;
            // keep listener record reference, in case someone will remove it while in callback
            RecordHolder<ListenerRecord> record(*it);

            /*
             * We pass lock here to allow modifying ops on EventSource inside callback
             * in active mode. Note that we expect list iterator stability as 'alock'
             * could be temporary released when calling event handler.
             */
            cbRc = record.obj()->process(aEvent, aWaitable, pit, alock);

            /* Note that E_ABORT is used above to signal that a passive
             * listener was unregistered due to not picking up its event.
             * This overlaps with XPCOM specific use of E_ABORT to signal
             * death of an active listener, but that's irrelevant here. */
            if (FAILED_DEAD_INTERFACE(cbRc) || cbRc == E_ABORT)
            {
                Listeners::iterator lit = m->mListeners.find(record.obj()->mListener);
                if (lit != m->mListeners.end())
                    m->mListeners.erase(lit);
            }
            // anything else to do with cbRc?
        }
    } while (0);
    /* We leave the lock here */

    if (aWaitable)
        hrc = aEvent->WaitProcessed(aTimeout, aProcessed);
    else
        *aProcessed = TRUE;

    return hrc;
}