Example #1
0
static int vmListBuild()
{
    serviceLogVerbose(("Building VM list ...\n"));

    int rc = RTCritSectEnter(&g_csMachines);
    if (RT_SUCCESS(rc))
    {
        /*
         * Make sure the list is empty.
         */
        g_mapVM.clear();

        /*
         * Get the list of all _running_ VMs
         */
        com::SafeIfaceArray<IMachine> machines;
        HRESULT hrc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
        if (SUCCEEDED(hrc))
        {
            /*
             * Iterate through the collection
             */
            for (size_t i = 0; i < machines.size(); ++i)
            {
                if (machines[i])
                {
                    Bstr strUUID;
                    CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(strUUID.asOutParam()));

                    BOOL fAccessible;
                    CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
                    if (!fAccessible)
                    {
                        serviceLogVerbose(("Machine \"%ls\" is inaccessible, skipping\n",
                                           strUUID.raw()));
                        continue;
                    }

                    rc = machineAdd(strUUID);
                    if (RT_FAILURE(rc))
                        break;
                }
            }

            if (!machines.size())
                serviceLogVerbose(("No machines to add found at the moment!\n"));
        }

        int rc2 = RTCritSectLeave(&g_csMachines);
        if (RT_SUCCESS(rc))
            rc = rc2;
    }
    return rc;
}
/**
 * List video capture devices.
 *
 * @returns See produceList.
 * @param   pVirtualBox         Reference to the IVirtualBox pointer.
 */
static HRESULT listVideoInputDevices(const ComPtr<IVirtualBox> pVirtualBox)
{
    HRESULT rc;
    ComPtr<IHost> host;
    CHECK_ERROR(pVirtualBox, COMGETTER(Host)(host.asOutParam()));
    com::SafeIfaceArray<IHostVideoInputDevice> hostVideoInputDevices;
    CHECK_ERROR(host, COMGETTER(VideoInputDevices)(ComSafeArrayAsOutParam(hostVideoInputDevices)));
    RTPrintf("Video Input Devices: %u\n", hostVideoInputDevices.size());
    for (size_t i = 0; i < hostVideoInputDevices.size(); ++i)
    {
        ComPtr<IHostVideoInputDevice> p = hostVideoInputDevices[i];
        Bstr name;
        p->COMGETTER(Name)(name.asOutParam());
        Bstr path;
        p->COMGETTER(Path)(path.asOutParam());
        Bstr alias;
        p->COMGETTER(Alias)(alias.asOutParam());
        RTPrintf("%ls \"%ls\"\n%ls\n", alias.raw(), name.raw(), path.raw());
    }
    return rc;
}
/**
 * Print out progress on the console.
 *
 * This runs the main event queue every now and then to prevent piling up
 * unhandled things (which doesn't cause real problems, just makes things
 * react a little slower than in the ideal case).
 */
DECLHIDDEN(HRESULT) showProgress(ComPtr<IProgress> progress)
{
    using namespace com;

    BOOL fCompleted = FALSE;
    ULONG ulCurrentPercent = 0;
    ULONG ulLastPercent = 0;

    ULONG ulLastOperationPercent = (ULONG)-1;

    ULONG ulLastOperation = (ULONG)-1;
    Bstr bstrOperationDescription;

    NativeEventQueue::getMainEventQueue()->processEventQueue(0);

    ULONG cOperations = 1;
    HRESULT hrc = progress->COMGETTER(OperationCount)(&cOperations);
    if (FAILED(hrc))
        return hrc;

    /* setup signal handling if cancelable */
    bool fCanceledAlready = false;
    BOOL fCancelable;
    hrc = progress->COMGETTER(Cancelable)(&fCancelable);
    if (FAILED(hrc))
        fCancelable = FALSE;

    hrc = progress->COMGETTER(Completed(&fCompleted));
    while (SUCCEEDED(hrc))
    {
        progress->COMGETTER(Percent(&ulCurrentPercent));

        if (fCompleted)
            break;

        /* process async cancelation */
        if (!fCanceledAlready)
        {
            hrc = progress->Cancel();
            if (SUCCEEDED(hrc))
                fCanceledAlready = true;
        }

        /* make sure the loop is not too tight */
        progress->WaitForCompletion(100);

        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
        hrc = progress->COMGETTER(Completed(&fCompleted));
    }

    /* complete the line. */
    LONG iRc = E_FAIL;
    hrc = progress->COMGETTER(ResultCode)(&iRc);
    if (SUCCEEDED(hrc))
    {
        hrc = iRc;
    }

    return hrc;
}
Example #4
0
HRESULT EventSource::eventProcessed(const ComPtr<IEventListener> &aListener,
                                    const ComPtr<IEvent> &aEvent)
{
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);

    if (m->fShutdown)
        return setError(VBOX_E_INVALID_OBJECT_STATE,
                        tr("This event source is already shut down"));

    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;
}
 STDMETHOD(OnMouseCapabilityChange) (BOOL supportsAbsolute, BOOL needsHostCursor)
 {
     /* Emit absolute mouse event to actually enable the host mouse cursor. */
     if (supportsAbsolute && gConsole)
     {
         ComPtr<IMouse> mouse;
         gConsole->COMGETTER(Mouse)(mouse.asOutParam());
         if (mouse)
         {
             mouse->PutMouseEventAbsolute(-1, -1, 0, 0 /* Horizontal wheel */, 0);
         }
     }
     return S_OK;
 }
Example #6
0
HRESULT VBoxNetDhcp::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
{
    switch (aEventType)
    {
        case VBoxEventType_OnHostNameResolutionConfigurationChange:
            fetchAndUpdateDnsInfo();
            break;

        case VBoxEventType_OnNATNetworkStartStop:
        {
            ComPtr <INATNetworkStartStopEvent> pStartStopEvent = pEvent;

            com::Bstr networkName;
            HRESULT hrc = pStartStopEvent->COMGETTER(NetworkName)(networkName.asOutParam());
            AssertComRCReturn(hrc, hrc);
            if (networkName.compare(getNetworkName().c_str()))
                break; /* change not for our network */

            BOOL fStart = TRUE;
            hrc = pStartStopEvent->COMGETTER(StartEvent)(&fStart);
            AssertComRCReturn(hrc, hrc);
            if (!fStart)
                shutdown();
            break;
        }

        case VBoxEventType_OnVBoxSVCAvailabilityChanged:
        {
            shutdown();
            break;
        }

        default: break; /* Shut up MSC. */
    }

    return S_OK;
}
int main()
{
    /*
     * Initialization.
     */
    RTEXITCODE rcExit = RTTestInitAndCreate("tstVBoxAPI", &g_hTest);
    if (rcExit != RTEXITCODE_SUCCESS)
        return rcExit;
    SUPR3Init(NULL); /* Better time support. */
    RTTestBanner(g_hTest);

    RTTestSub(g_hTest, "Initializing COM and singletons");
    HRESULT hrc = com::Initialize();
    if (SUCCEEDED(hrc))
    {
        ComPtr<IVirtualBoxClient> ptrVBoxClient;
        ComPtr<IVirtualBox> ptrVBox;
        hrc = TST_COM_EXPR(ptrVBoxClient.createInprocObject(CLSID_VirtualBoxClient));
        if (SUCCEEDED(hrc))
            hrc = TST_COM_EXPR(ptrVBoxClient->COMGETTER(VirtualBox)(ptrVBox.asOutParam()));
        if (SUCCEEDED(hrc))
        {
            ComPtr<ISession> ptrSession;
            hrc = TST_COM_EXPR(ptrSession.createInprocObject(CLSID_Session));
            if (SUCCEEDED(hrc))
            {
                RTTestSubDone(g_hTest);

                /*
                 * Call test functions.
                 */

                /** Test IVirtualBox interface */
                tstApiIVirtualBox(ptrVBox);


                /** Clean files/configs */
                tstApiClean(ptrVBox);
            }
        }

        ptrVBox.setNull();
        ptrVBoxClient.setNull();
        com::Shutdown();
    }
    else
        RTTestIFailed("com::Initialize failed with hrc=%Rhrc", hrc);
    return RTTestSummaryAndDestroy(g_hTest);
}
Example #8
0
int NetIfRemoveHostOnlyNetworkInterface(VirtualBox *pVirtualBox, IN_GUID aId,
                                        IProgress **aProgress)
{
#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
    /* create a progress object */
    ComObjPtr<Progress> progress;
    progress.createObject();
    ComPtr<IHost> host;
    int rc = VINF_SUCCESS;
    HRESULT hr = pVirtualBox->COMGETTER(Host)(host.asOutParam());
    if (SUCCEEDED(hr))
    {
        Bstr ifname;
        ComPtr<IHostNetworkInterface> iface;
        if (FAILED(host->FindHostNetworkInterfaceById(Guid(aId).toUtf16().raw(), iface.asOutParam())))
            return VERR_INVALID_PARAMETER;
        iface->COMGETTER(Name)(ifname.asOutParam());
        if (ifname.isEmpty())
            return VERR_INTERNAL_ERROR;

        rc = progress->init(pVirtualBox, host,
                            Bstr("Removing host network interface").raw(),
                            FALSE /* aCancelable */);
        if (SUCCEEDED(rc))
        {
            progress.queryInterfaceTo(aProgress);
            rc = NetIfAdpCtl(Utf8Str(ifname).c_str(), "remove", NULL, NULL);
            if (RT_FAILURE(rc))
                progress->i_notifyComplete(E_FAIL,
                                           COM_IIDOF(IHostNetworkInterface),
                                           HostNetworkInterface::getStaticComponentName(),
                                           "Failed to execute '" VBOXNETADPCTL_NAME "' (exit status: %d)", rc);
            else
                progress->i_notifyComplete(S_OK);
        }
    }
    else
    {
        progress->i_notifyComplete(hr);
        rc = VERR_INTERNAL_ERROR;
    }
    return rc;
#else
    NOREF(pVirtualBox);
    NOREF(aId);
    NOREF(aProgress);
    return VERR_NOT_IMPLEMENTED;
#endif
}
HRESULT CollectorGuest::enableInternal(ULONG mask)
{
    HRESULT ret = S_OK;

    if ((mEnabled & mask) == mask)
        return E_UNEXPECTED;

    if (!mEnabled)
    {
        /* Must make sure that the machine object does not get uninitialized
         * in the middle of enabling this collector. Causes timing-related
         * behavior otherwise, which we don't want. In particular the
         * GetRemoteConsole call below can hang if the VM didn't completely
         * terminate (the VM processes stop processing events shortly before
         * closing the session). This avoids the hang. */
        AutoCaller autoCaller(mMachine);
        if (FAILED(autoCaller.rc())) return autoCaller.rc();

        mMachineName = mMachine->i_getName();

        ComPtr<IInternalSessionControl> directControl;

        ret = mMachine->i_getDirectControl(&directControl);
        if (ret != S_OK)
            return ret;

        /* get the associated console; this is a remote call (!) */
        ret = directControl->COMGETTER(RemoteConsole)(mConsole.asOutParam());
        if (ret != S_OK)
            return ret;

        ret = mConsole->COMGETTER(Guest)(mGuest.asOutParam());
        if (ret == S_OK)
        {
            ret = mGuest->COMSETTER(StatisticsUpdateInterval)(1 /* 1 sec */);
            LogAleksey(("{%p} " LOG_FN_FMT ": Set guest statistics update interval to 1 sec (%s)\n",
                        this, __PRETTY_FUNCTION__, SUCCEEDED(ret)?"success":"failed"));
        }
    }
    if ((mask & VMSTATS_VMM_RAM) == VMSTATS_VMM_RAM)
        enableVMMStats(true);
    mEnabled |= mask;

    return ret;
}
STDMETHODIMP VRDEServer::COMGETTER(VRDEExtPack) (BSTR *aExtPack)
{
    CheckComArgOutPointerValid(aExtPack);

    AutoCaller autoCaller(this);
    HRESULT hrc = autoCaller.rc();
    if (SUCCEEDED(hrc))
    {
        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
        Utf8Str strExtPack = mData->mVrdeExtPack;
        alock.release();

        if (strExtPack.isNotEmpty())
        {
            if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
                hrc = S_OK;
            else
            {
#ifdef VBOX_WITH_EXTPACK
                ExtPackManager *pExtPackMgr = mParent->getVirtualBox()->getExtPackManager();
                hrc = pExtPackMgr->checkVrdeExtPack(&strExtPack);
#else
                hrc = setError(E_FAIL, tr("Extension pack '%s' does not exist"), strExtPack.c_str());
#endif
            }
            if (SUCCEEDED(hrc))
                strExtPack.cloneTo(aExtPack);
        }
        else
        {
            /* Get the global setting. */
            ComPtr<ISystemProperties> systemProperties;
            hrc = mParent->getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam());
            if (SUCCEEDED(hrc))
                hrc = systemProperties->COMGETTER(DefaultVRDEExtPack)(aExtPack);
        }
    }

    return hrc;
}
/**
 * Creates all global COM objects.
 *
 * @return  HRESULT
 */
static int watchdogSetup()
{
    serviceLogVerbose(("Setting up ...\n"));

    /*
     * Setup VirtualBox + session interfaces.
     */
    HRESULT rc = g_pVirtualBoxClient->COMGETTER(VirtualBox)(g_pVirtualBox.asOutParam());
    if (SUCCEEDED(rc))
    {
        rc = g_pSession.createInprocObject(CLSID_Session);
        if (FAILED(rc))
            RTMsgError("Failed to create a session object (rc=%Rhrc)!", rc);
    }
    else
        RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc);

    if (FAILED(rc))
        return VERR_COM_OBJECT_NOT_FOUND;

    /*
     * Setup metrics.
     */
#ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
    CHECK_ERROR_RET(g_pVirtualBox,
                    COMGETTER(PerformanceCollector)(g_pPerfCollector.asOutParam()), VERR_COM_UNEXPECTED);
#endif

    int vrc = RTCritSectInit(&g_csMachines);
    if (RT_SUCCESS(vrc))
    {

        /*
         * Build up initial VM list.
         */
        vrc = vmListBuild();
    }

    return vrc;
}
Example #12
0
HRESULT DHCPServer::getMacOptions(const com::Utf8Str &aMAC, std::vector<com::Utf8Str> &aOption)
{
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    HRESULT hrc = S_OK;
    ComPtr<IMachine> machine;
    ComPtr<INetworkAdapter> nic;
    settings::VmSlot2OptionsIterator it;
    for(it = m->VmSlot2Options.begin(); it != m->VmSlot2Options.end(); ++it)
    {
        alock.release();
        hrc = mVirtualBox->FindMachine(Bstr(it->first.VmName).raw(), machine.asOutParam());
        alock.acquire();

        if (FAILED(hrc))
            continue;

        alock.release();
        hrc = machine->GetNetworkAdapter(it->first.Slot, nic.asOutParam());
        alock.acquire();

        if (FAILED(hrc))
            continue;

        com::Bstr mac;

        alock.release();
        hrc = nic->COMGETTER(MACAddress)(mac.asOutParam());
        alock.acquire();

        if (FAILED(hrc)) /* no MAC address ??? */
            break;
        if (!RTStrICmp(com::Utf8Str(mac).c_str(), aMAC.c_str()))
            return getVmSlotOptions(it->first.VmName,
                                    it->first.Slot,
                                    aOption);
    } /* end of for */

    return hrc;
}
Example #13
0
ListenerRecord::~ListenerRecord()
{
    /* Remove references to us from the event map */
    EventMap* aEvMap = &mOwner->m->mEvMap;
    for (int j = FirstEvent; j < LastEvent; j++)
    {
        (*aEvMap)[j - FirstEvent].remove(this);
    }

    if (!mActive)
    {
        // at this moment nobody could add elements to our queue, so we can safely
        // clean it up, otherwise there will be pending events map elements
        PendingEventsMap* aPem = &mOwner->m->mPendingMap;
        while (true)
        {
            ComPtr<IEvent> aEvent;

            if (mQueue.empty())
                break;

            mQueue.front().queryInterfaceTo(aEvent.asOutParam());
            mQueue.pop_front();

            BOOL aWaitable = FALSE;
            aEvent->COMGETTER(Waitable)(&aWaitable);
            if (aWaitable)
            {
                PendingEventsMap::iterator pit = aPem->find(aEvent);
                if (pit != aPem->end())
                    eventProcessed(aEvent, pit);
            }
        }

        ::RTCritSectDelete(&mcsQLock);
        ::RTSemEventDestroy(mQEvent);
    }
}
HRESULT VRDEServer::getVRDEExtPack(com::Utf8Str &aExtPack)
{
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    Utf8Str strExtPack = mData->mVrdeExtPack;
    alock.release();
    HRESULT hrc = S_OK;

    if (strExtPack.isNotEmpty())
    {
        if (strExtPack.equals(VBOXVRDP_KLUDGE_EXTPACK_NAME))
            hrc = S_OK;
        else
        {
#ifdef VBOX_WITH_EXTPACK
            ExtPackManager *pExtPackMgr = mParent->i_getVirtualBox()->i_getExtPackManager();
            hrc = pExtPackMgr->i_checkVrdeExtPack(&strExtPack);
#else
            hrc = setError(E_FAIL, tr("Extension pack '%s' does not exist"), strExtPack.c_str());
#endif
        }
        if (SUCCEEDED(hrc))
            aExtPack = strExtPack;
    }
    else
    {
        /* Get the global setting. */
        ComPtr<ISystemProperties> systemProperties;
        hrc = mParent->i_getVirtualBox()->COMGETTER(SystemProperties)(systemProperties.asOutParam());
        if (SUCCEEDED(hrc))
        {
            BSTR bstr;
            hrc = systemProperties->COMGETTER(DefaultVRDEExtPack)(&bstr);
            if (SUCCEEDED(hrc))
                aExtPack = Utf8Str(bstr);
        }
    }
    return hrc;
}
static int balloonSetSize(PVBOXWATCHDOG_MACHINE pMachine, uint32_t cMbBalloonCur)
{
    int vrc = VINF_SUCCESS;

    serviceLogVerbose(("[%ls] Setting balloon size to %RU32MB ...\n", pMachine->strName.raw(), cMbBalloonCur));

    if (g_fDryrun)
        return VINF_SUCCESS;

    /* Open a session for the VM. */
    HRESULT rc;
    CHECK_ERROR_RET(pMachine->machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED);

    do
    {
        /* Get the associated console. */
        ComPtr<IConsole> console;
        CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));

        ComPtr <IGuest> guest;
        rc = console->COMGETTER(Guest)(guest.asOutParam());
        if (SUCCEEDED(rc))
            CHECK_ERROR_BREAK(guest, COMSETTER(MemoryBalloonSize)((LONG)cMbBalloonCur));
        else
            serviceLog("Error: Unable to set new balloon size %RU32 for machine '%ls', rc=%Rhrc\n",
                       cMbBalloonCur, pMachine->strName.raw(), rc);
        if (FAILED(rc))
            vrc = VERR_COM_IPRT_ERROR;

    } while (0);


    /* Unlock the machine again. */
    CHECK_ERROR_RET(g_pSession,  UnlockMachine(), VERR_ACCESS_DENIED);

    return vrc;
}
Example #16
0
HRESULT Progress::waitForAsyncProgressCompletion(const ComPtr<IProgress> &aPProgressAsync)
{
    LogFlowThisFuncEnter();

    /* 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 = aPProgressAsync->COMGETTER(Cancelable)(&fCancelable);
    if (FAILED(rc)) return rc;
    /* Loop as long as the sync process isn't completed. */
    while (SUCCEEDED(aPProgressAsync->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 = aPProgressAsync->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 = aPProgressAsync->COMGETTER(Operation(&curOp));
                if (FAILED(rc)) return rc;
                if (cOp != curOp)
                {
                    Bstr bstr;
                    ULONG currentWeight;
                    rc = aPProgressAsync->COMGETTER(OperationDescription(bstr.asOutParam()));
                    if (FAILED(rc)) return rc;
                    rc = aPProgressAsync->COMGETTER(OperationWeight(&currentWeight));
                    if (FAILED(rc)) return rc;
                    rc = SetNextOperation(bstr.raw(), currentWeight);
                    if (FAILED(rc)) return rc;
                    ++cOp;
                }
                else
                    break;
            }

            rc = aPProgressAsync->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 = aPProgressAsync->WaitForCompletion(100);
        if (FAILED(rc)) return rc;
    }

    LogFlowThisFuncLeave();

    return rc;
}
/**
 * Called to copy over the progress information from @a pOtherProgress.
 *
 * @param   pOtherProgress  The source of the information.
 * @param   fEarly          Early copy.
 *
 * @note    The caller owns the write lock and as cleared mptrOtherProgress
 *          already (or we might recurse forever)!
 */
void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly)
{
    HRESULT hrc;
    LogFlowThisFunc(("\n"));

    NOREF(fEarly);

    /*
     * No point in doing this if the progress object was canceled already.
     */
    if (!mCanceled)
    {
        /* Detect if the other progress object was canceled. */
        BOOL fCanceled;
        hrc = pOtherProgress->COMGETTER(Canceled)(&fCanceled);
        if (FAILED(hrc))
            fCanceled = FALSE;
        if (fCanceled)
        {
            LogFlowThisFunc(("Canceled\n"));
            mCanceled = TRUE;
            if (m_pfnCancelCallback)
                m_pfnCancelCallback(m_pvCancelUserArg);
        }
        else
        {
            /* Has it completed? */
            BOOL fCompleted;
            hrc = pOtherProgress->COMGETTER(Completed)(&fCompleted);
            if (FAILED(hrc))
                fCompleted = TRUE;
            Assert(fCompleted || fEarly);
            if (fCompleted)
            {
                /* Check the result. */
                LONG hrcResult;
                hrc = pOtherProgress->COMGETTER(ResultCode)(&hrcResult);
                if (FAILED(hrc))
                    hrcResult = hrc;
                if (SUCCEEDED((HRESULT)hrcResult))
                    LogFlowThisFunc(("Succeeded\n"));
                else
                {
                    /* Get the error information. */
                    ComPtr<IVirtualBoxErrorInfo> ptrErrorInfo;
                    hrc = pOtherProgress->COMGETTER(ErrorInfo)(ptrErrorInfo.asOutParam());
                    if (SUCCEEDED(hrc) && !ptrErrorInfo.isNull())
                    {
                        Bstr bstrIID;
                        hrc = ptrErrorInfo->COMGETTER(InterfaceID)(bstrIID.asOutParam()); AssertComRC(hrc);
                        if (FAILED(hrc))
                            bstrIID.setNull();

                        Bstr bstrComponent;
                        hrc = ptrErrorInfo->COMGETTER(Component)(bstrComponent.asOutParam()); AssertComRC(hrc);
                        if (FAILED(hrc))
                            bstrComponent = "failed";

                        Bstr bstrText;
                        hrc = ptrErrorInfo->COMGETTER(Text)(bstrText.asOutParam()); AssertComRC(hrc);
                        if (FAILED(hrc))
                            bstrText = "<failed>";

                        Utf8Str strText(bstrText);
                        LogFlowThisFunc(("Got ErrorInfo(%s); hrcResult=%Rhrc\n", strText.c_str(), hrcResult));
                        Progress::notifyComplete((HRESULT)hrcResult,
                                                 Guid(bstrIID).ref(),
                                                 Utf8Str(bstrComponent).c_str(),
                                                 "%s", strText.c_str());
                    }
                    else
                    {
                        LogFlowThisFunc(("ErrorInfo failed with hrc=%Rhrc; hrcResult=%Rhrc\n", hrc, hrcResult));
                        Progress::notifyComplete((HRESULT)hrcResult,
                                                 COM_IIDOF(IProgress),
                                                 "ProgressProxy",
                                                 tr("No error info"));
                    }
                }
            }
            else
                LogFlowThisFunc(("Not completed\n"));
        }
    }
    else
        LogFlowThisFunc(("Already canceled\n"));

    /*
     * Did cancelable state change (point of no return)?
     */
    if (mCancelable && !mCompleted && !mCanceled)
    {
        BOOL fCancelable;
        hrc = pOtherProgress->COMGETTER(Cancelable)(&fCancelable); AssertComRC(hrc);
        if (SUCCEEDED(hrc) && !fCancelable)
        {
            LogFlowThisFunc(("point-of-no-return reached\n"));
            mCancelable = FALSE;
        }
    }
}
/**
 * Sets the other progress object unless the operation has been completed /
 * canceled already.
 *
 * @returns false if failed/canceled, true if not.
 * @param   pOtherProgress      The other progress object. Must not be NULL.
 */
bool ProgressProxy::setOtherProgressObject(IProgress *pOtherProgress)
{
    LogFlowThisFunc(("setOtherProgressObject: %p\n", pOtherProgress));
    ComPtr<IProgress> ptrOtherProgress = pOtherProgress;

    /*
     * Query information from the other progress object before we grab the
     * lock.
     */
    ULONG cOperations;
    HRESULT hrc = pOtherProgress->COMGETTER(OperationCount)(&cOperations);
    if (FAILED(hrc))
        cOperations = 1;

    Bstr bstrOperationDescription;
    hrc = pOtherProgress->COMGETTER(Description)(bstrOperationDescription.asOutParam());
    if (FAILED(hrc))
        bstrOperationDescription = "oops";


    /*
     * Take the lock and check for cancelation, cancel the other object if
     * we've been canceled already.
     */
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    BOOL fCompletedOrCanceled = mCompleted || mCanceled;
    if (!fCompletedOrCanceled)
    {
        /*
         * Advance to the next object and operation. If the other object has
         * more operations than anticipated, adjust our internal count.
         */
        mptrOtherProgress = ptrOtherProgress;
        mfMultiOperation  = cOperations > 1;

        muOtherProgressStartWeight = m_ulOperationsCompletedWeight + m_ulCurrentOperationWeight;
        muOtherProgressWeight      = m_ulTotalOperationsWeight - muOtherProgressStartWeight;
        Progress::SetNextOperation(bstrOperationDescription.raw(), muOtherProgressWeight);

        muOtherProgressStartOperation = m_ulCurrentOperation;
        m_cOperations = cOperations + m_ulCurrentOperation;

        /*
         * Check for cancelation and completion.
         */
        BOOL f;
        hrc = ptrOtherProgress->COMGETTER(Completed)(&f);
        fCompletedOrCanceled = FAILED(hrc) || f;

        if (!fCompletedOrCanceled)
        {
            hrc = ptrOtherProgress->COMGETTER(Canceled)(&f);
            fCompletedOrCanceled = SUCCEEDED(hrc) && f;
        }

        if (fCompletedOrCanceled)
        {
            LogFlowThisFunc(("Other object completed or canceled, clearing...\n"));
            clearOtherProgressObjectInternal(false /*fEarly*/);
        }
        else
        {
            /*
             * Finally, mirror the cancelable property.
             * Note! Note necessary if we do passthru!
             */
            if (mCancelable)
            {
                hrc = ptrOtherProgress->COMGETTER(Cancelable)(&f);
                if (SUCCEEDED(hrc) && !f)
                {
                    LogFlowThisFunc(("The other progress object is not cancelable\n"));
                    mCancelable = FALSE;
                }
            }
        }
    }
    else
    {
        LogFlowThisFunc(("mCompleted=%RTbool mCanceled=%RTbool - Canceling the other progress object!\n",
                         mCompleted, mCanceled));
        hrc = ptrOtherProgress->Cancel();
        LogFlowThisFunc(("Cancel -> %Rhrc", hrc));
    }

    LogFlowThisFunc(("Returns %RTbool\n", !fCompletedOrCanceled));
    return !fCompletedOrCanceled;
}
HRESULT showMediumInfo(const ComPtr<IVirtualBox> &pVirtualBox,
                       const ComPtr<IMedium> &pMedium,
                       const char *pszParentUUID,
                       bool fOptLong)
{
    HRESULT rc = S_OK;
    do
    {
        Bstr uuid;
        pMedium->COMGETTER(Id)(uuid.asOutParam());
        RTPrintf("UUID:           %ls\n", uuid.raw());
        if (pszParentUUID)
            RTPrintf("Parent UUID:    %s\n", pszParentUUID);

        /* check for accessibility */
        MediumState_T enmState;
        CHECK_ERROR_BREAK(pMedium, RefreshState(&enmState));
        pMedium->RefreshState(&enmState);
        const char *pszState = "unknown";
        switch (enmState)
        {
            case MediumState_NotCreated:
                pszState = "not created";
                break;
            case MediumState_Created:
                pszState = "created";
                break;
            case MediumState_LockedRead:
                pszState = "locked read";
                break;
            case MediumState_LockedWrite:
                pszState = "locked write";
                break;
            case MediumState_Inaccessible:
                pszState = "inaccessible";
                break;
            case MediumState_Creating:
                pszState = "creating";
                break;
            case MediumState_Deleting:
                pszState = "deleting";
                break;
        }
        RTPrintf("State:          %s\n", pszState);

        if (fOptLong && enmState == MediumState_Inaccessible)
        {
            Bstr err;
            CHECK_ERROR_BREAK(pMedium, COMGETTER(LastAccessError)(err.asOutParam()));
            RTPrintf("Access Error:   %ls\n", err.raw());
        }

        if (fOptLong)
        {
            Bstr description;
            pMedium->COMGETTER(Description)(description.asOutParam());
            if (!description.isEmpty())
                RTPrintf("Description:    %ls\n", description.raw());
        }

        MediumType_T type;
        pMedium->COMGETTER(Type)(&type);
        const char *typeStr = "unknown";
        switch (type)
        {
            case MediumType_Normal:
                if (pszParentUUID && Guid(pszParentUUID).isValid())
                    typeStr = "normal (differencing)";
                else
                    typeStr = "normal (base)";
                break;
            case MediumType_Immutable:
                typeStr = "immutable";
                break;
            case MediumType_Writethrough:
                typeStr = "writethrough";
                break;
            case MediumType_Shareable:
                typeStr = "shareable";
                break;
            case MediumType_Readonly:
                typeStr = "readonly";
                break;
            case MediumType_MultiAttach:
                typeStr = "multiattach";
                break;
        }
        RTPrintf("Type:           %s\n", typeStr);

        /* print out information specific for differencing hard disks */
        if (fOptLong && pszParentUUID && Guid(pszParentUUID).isValid())
        {
            BOOL autoReset = FALSE;
            pMedium->COMGETTER(AutoReset)(&autoReset);
            RTPrintf("Auto-Reset:     %s\n", autoReset ? "on" : "off");
        }

        Bstr loc;
        pMedium->COMGETTER(Location)(loc.asOutParam());
        RTPrintf("Location:       %ls\n", loc.raw());

        Bstr format;
        pMedium->COMGETTER(Format)(format.asOutParam());
        RTPrintf("Storage format: %ls\n", format.raw());

        if (fOptLong)
        {
            com::SafeArray<MediumVariant_T> safeArray_variant;

            pMedium->COMGETTER(Variant)(ComSafeArrayAsOutParam(safeArray_variant));
            ULONG variant=0;
            for (size_t i = 0; i < safeArray_variant.size(); i++)
                variant |= safeArray_variant[i];

            const char *variantStr = "unknown";
            switch (variant & ~(MediumVariant_Fixed | MediumVariant_Diff))
            {
                case MediumVariant_VmdkSplit2G:
                    variantStr = "split2G";
                    break;
                case MediumVariant_VmdkStreamOptimized:
                    variantStr = "streamOptimized";
                    break;
                case MediumVariant_VmdkESX:
                    variantStr = "ESX";
                    break;
                case MediumVariant_Standard:
                    variantStr = "default";
                    break;
            }
            const char *variantTypeStr = "dynamic";
            if (variant & MediumVariant_Fixed)
                variantTypeStr = "fixed";
            else if (variant & MediumVariant_Diff)
                variantTypeStr = "differencing";
            RTPrintf("Format variant: %s %s\n", variantTypeStr, variantStr);
        }

        LONG64 logicalSize;
        pMedium->COMGETTER(LogicalSize)(&logicalSize);
        RTPrintf("Capacity:       %lld MBytes\n", logicalSize >> 20);
        if (fOptLong)
        {
            LONG64 actualSize;
            pMedium->COMGETTER(Size)(&actualSize);
            RTPrintf("Size on disk:   %lld MBytes\n", actualSize >> 20);
        }

        if (fOptLong)
        {
            com::SafeArray<BSTR> names;
            com::SafeArray<BSTR> values;
            pMedium->GetProperties(Bstr().raw(), ComSafeArrayAsOutParam(names), ComSafeArrayAsOutParam(values));
            size_t cNames = names.size();
            size_t cValues = values.size();
            bool fFirst = true;
            for (size_t i = 0; i < cNames; i++)
            {
                Bstr value;
                if (i < cValues)
                    value = values[i];
                RTPrintf("%s%ls=%ls\n",
                         fFirst ? "Property:       " : "                ",
                         names[i], value.raw());
            }
        }

        if (fOptLong)
        {
            bool fFirst = true;
            com::SafeArray<BSTR> machineIds;
            pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));
            for (size_t i = 0; i < machineIds.size(); i++)
            {
                ComPtr<IMachine> machine;
                CHECK_ERROR(pVirtualBox, FindMachine(machineIds[i], machine.asOutParam()));
                if (machine)
                {
                    Bstr name;
                    machine->COMGETTER(Name)(name.asOutParam());
                    machine->COMGETTER(Id)(uuid.asOutParam());
                    RTPrintf("%s%ls (UUID: %ls)",
                             fFirst ? "In use by VMs:  " : "                ",
                             name.raw(), machineIds[i]);
                    fFirst = false;
                    com::SafeArray<BSTR> snapshotIds;
                    pMedium->GetSnapshotIds(machineIds[i],
                                            ComSafeArrayAsOutParam(snapshotIds));
                    for (size_t j = 0; j < snapshotIds.size(); j++)
                    {
                        ComPtr<ISnapshot> snapshot;
                        machine->FindSnapshot(snapshotIds[j], snapshot.asOutParam());
                        if (snapshot)
                        {
                            Bstr snapshotName;
                            snapshot->COMGETTER(Name)(snapshotName.asOutParam());
                            RTPrintf(" [%ls (UUID: %ls)]", snapshotName.raw(), snapshotIds[j]);
                        }
                    }
                    RTPrintf("\n");
                }
            }
        }

        if (fOptLong)
        {
            com::SafeIfaceArray<IMedium> children;
            pMedium->COMGETTER(Children)(ComSafeArrayAsOutParam(children));
            bool fFirst = true;
            for (size_t i = 0; i < children.size(); i++)
            {
                ComPtr<IMedium> pChild(children[i]);
                if (pChild)
                {
                    Bstr childUUID;
                    pChild->COMGETTER(Id)(childUUID.asOutParam());
                    RTPrintf("%s%ls\n",
                             fFirst ? "Child UUIDs:    " : "                ",
                             childUUID.raw());
                    fFirst = false;
                }
            }
        }
    }
    while (0);

    return rc;
}
int handleShowHardDiskInfo(HandlerArg *a)
{
    HRESULT rc;
    const char *FilenameOrUuid = NULL;

    int c;
    RTGETOPTUNION ValueUnion;
    RTGETOPTSTATE GetState;
    // start at 0 because main() has hacked both the argc and argv given to us
    RTGetOptInit(&GetState, a->argc, a->argv, g_aShowHardDiskInfoOptions, RT_ELEMENTS(g_aShowHardDiskInfoOptions),
                 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    while ((c = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (c)
        {
            case VINF_GETOPT_NOT_OPTION:
                if (!FilenameOrUuid)
                    FilenameOrUuid = ValueUnion.psz;
                else
                    return errorSyntax(USAGE_SHOWHDINFO, "Invalid parameter '%s'", ValueUnion.psz);
                break;

            default:
                if (c > 0)
                {
                    if (RT_C_IS_PRINT(c))
                        return errorSyntax(USAGE_SHOWHDINFO, "Invalid option -%c", c);
                    else
                        return errorSyntax(USAGE_SHOWHDINFO, "Invalid option case %i", c);
                }
                else if (c == VERR_GETOPT_UNKNOWN_OPTION)
                    return errorSyntax(USAGE_SHOWHDINFO, "unknown option: %s\n", ValueUnion.psz);
                else if (ValueUnion.pDef)
                    return errorSyntax(USAGE_SHOWHDINFO, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
                else
                    return errorSyntax(USAGE_SHOWHDINFO, "error: %Rrs", c);
        }
    }

    /* check for required options */
    if (!FilenameOrUuid)
        return errorSyntax(USAGE_SHOWHDINFO, "Disk name or UUID required");

    ComPtr<IMedium> hardDisk;
    rc = openMedium(a, FilenameOrUuid, DeviceType_HardDisk,
                    AccessMode_ReadOnly, hardDisk,
                    false /* fForceNewUuidOnOpen */, false /* fSilent */);
    if (FAILED(rc))
        return 1;

    Utf8Str strParentUUID("base");
    ComPtr<IMedium> parent;
    hardDisk->COMGETTER(Parent)(parent.asOutParam());
    if (!parent.isNull())
    {
        Bstr bstrParentUUID;
        parent->COMGETTER(Id)(bstrParentUUID.asOutParam());
        strParentUUID = bstrParentUUID;
    }

    rc = showMediumInfo(a->virtualBox, hardDisk, strParentUUID.c_str(), true);

    return SUCCEEDED(rc) ? 0 : 1;
}
Example #21
0
DECLEXPORT(AuthResult) AUTHCALL AuthEntry(const char *szCaller,
                                          PAUTHUUID pUuid,
                                          AuthGuestJudgement guestJudgement,
                                          const char *szUser,
                                          const char *szPassword,
                                          const char *szDomain,
                                          int fLogon,
                                          unsigned clientId)
{
    /* default is failed */
    AuthResult result = AuthResultAccessDenied;

    /* only interested in logon */
    if (!fLogon)
        /* return value ignored */
        return result;

    char uuid[RTUUID_STR_LENGTH] = {0};
    if (pUuid)
        RTUuidToStr((PCRTUUID)pUuid, (char*)uuid, RTUUID_STR_LENGTH);

    /* the user might contain a domain name, split it */
    char *user = strchr((char*)szUser, '\\');
    if (user)
        user++;
    else
        user = (char*)szUser;

    dprintf("VBoxAuth: uuid: %s, user: %s, szPassword: %s\n", uuid, user, szPassword);

    ComPtr<IVirtualBoxClient> virtualBoxClient;
    ComPtr<IVirtualBox> virtualBox;
    HRESULT rc;

    rc = virtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
    if (SUCCEEDED(rc))
        rc = virtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam());
    if (SUCCEEDED(rc))
    {
        Bstr key = BstrFmt("VBoxAuthSimple/users/%s", user);
        Bstr password;

        /* lookup in VM's extra data? */
        if (pUuid)
        {
            ComPtr<IMachine> machine;
            virtualBox->FindMachine(Bstr(uuid).raw(), machine.asOutParam());
            if (machine)
                machine->GetExtraData(key.raw(), password.asOutParam());
        } else
            /* lookup global extra data */
            virtualBox->GetExtraData(key.raw(), password.asOutParam());

        if (!password.isEmpty())
        {
            /* calculate hash */
            uint8_t abDigest[RTSHA256_HASH_SIZE];
            RTSha256(szPassword, strlen(szPassword), abDigest);
            char pszDigest[RTSHA256_DIGEST_LEN + 1];
            RTSha256ToString(abDigest, pszDigest, sizeof(pszDigest));

            if (password == pszDigest)
                result = AuthResultAccessGranted;
        }
    }
    else
        dprintf("VBoxAuth: failed to get VirtualBox object reference: %Rhrc\n", rc);

    return result;
}
void HostPowerService::notify(Reason_T aReason)
{
    SessionMachinesList machines;
    VirtualBox::InternalControlList controls;

    HRESULT rc = S_OK;

    switch (aReason)
    {
        case Reason_HostSuspend:
        {
            LogFunc(("HOST SUSPEND\n"));

#ifdef VBOX_WITH_RESOURCE_USAGE_API
            /* Suspend performance sampling to avoid unnecessary callbacks due to jumps in time. */
            PerformanceCollector *perfcollector = mVirtualBox->i_performanceCollector();

            if (perfcollector)
                perfcollector->suspendSampling();
#endif
            mVirtualBox->i_getOpenedMachines(machines, &controls);

            /* pause running VMs */
            for (VirtualBox::InternalControlList::const_iterator it = controls.begin();
                 it != controls.end();
                 ++it)
            {
                ComPtr<IInternalSessionControl> pControl = *it;

                /* PauseWithReason() will simply return a failure if
                 * the VM is in an inappropriate state */
                rc = pControl->PauseWithReason(Reason_HostSuspend);
                if (FAILED(rc))
                    continue;

                /* save the control to un-pause the VM later */
                mSessionControls.push_back(pControl);
            }

            LogRel(("Host suspending: Paused %d VMs\n", mSessionControls.size()));
            break;
        }

        case Reason_HostResume:
        {
            LogFunc(("HOST RESUME\n"));

            size_t resumed = 0;

            /* go through VMs we paused on Suspend */
            for (size_t i = 0; i < mSessionControls.size(); ++i)
            {
                /* note that Resume() will simply return a failure if the VM is
                 * in an inappropriate state (it will also fail if the VM has
                 * been somehow closed by this time already so that the
                 * console reference we have is dead) */
                rc = mSessionControls[i]->ResumeWithReason(Reason_HostResume);
                if (FAILED(rc))
                    continue;

                ++resumed;
            }

            LogRel(("Host resumed: Resumed %d VMs\n", resumed));

#ifdef VBOX_WITH_RESOURCE_USAGE_API
            /* Resume the performance sampling. */
            PerformanceCollector *perfcollector = mVirtualBox->i_performanceCollector();

            if (perfcollector)
                perfcollector->resumeSampling();
#endif

            mSessionControls.clear();
            break;
        }

        case Reason_HostBatteryLow:
        {
            LogFunc(("BATTERY LOW\n"));

            Bstr value;
            rc = mVirtualBox->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(),
                                           value.asOutParam());
            int fGlobal = 0;
            if (SUCCEEDED(rc) && !value.isEmpty())
            {
                if (value != "0")
                    fGlobal = 1;
                else if (value == "0")
                    fGlobal = -1;
            }

            mVirtualBox->i_getOpenedMachines(machines, &controls);
            size_t saved = 0;

            /* save running VMs */
            for (SessionMachinesList::const_iterator it = machines.begin();
                 it != machines.end();
                 ++it)
            {
                ComPtr<SessionMachine> pMachine = *it;
                rc = pMachine->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(),
                                            value.asOutParam());
                int fPerVM = 0;
                if (SUCCEEDED(rc) && !value.isEmpty())
                {
                    /* per-VM overrides global */
                    if (value != "0")
                        fPerVM = 2;
                    else if (value == "0")
                        fPerVM = -2;
                }

                /* default is true */
                if (fGlobal + fPerVM >= 0)
                {
                    ComPtr<IProgress> progress;

                    /* SessionMachine::i_saveStateWithReason() will return
                     * a failure if the VM is in an inappropriate state */
                    rc = pMachine->i_saveStateWithReason(Reason_HostBatteryLow, progress);
                    if (FAILED(rc))
                    {
                        LogRel(("SaveState '%s' failed with %Rhrc\n", pMachine->i_getName().c_str(), rc));
                        continue;
                    }

                    /* Wait until the operation has been completed. */
                    rc = progress->WaitForCompletion(-1);
                    if (SUCCEEDED(rc))
                    {
                        LONG iRc;
                        progress->COMGETTER(ResultCode)(&iRc);
                        rc = iRc;
                    }

                    AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc));

                    if (SUCCEEDED(rc))
                    {
                        LogRel(("SaveState '%s' succeeded\n", pMachine->i_getName().c_str()));
                        ++saved;
                    }
                }
            }
            LogRel(("Battery Low: saved %d VMs\n", saved));
            break;
        }

        default:
            /* nothing */;
    }
}
int main(int argc, char *argv[])
{
    /*
     * Before we do anything, init the runtime without loading
     * the support driver.
     */
    int vrc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(vrc))
        return RTMsgInitFailure(vrc);
#if defined(RT_OS_WINDOWS) && !defined(VBOX_ONLY_DOCS)
    ATL::CComModule _Module; /* Required internally by ATL (constructor records instance in global variable). */
#endif

    /*
     * Parse the global options
     */
    bool fShowLogo = false;
    bool fShowHelp = false;
    int  iCmd      = 1;
    int  iCmdArg;
    const char *pszSettingsPw = NULL;
    const char *pszSettingsPwFile = NULL;
#ifndef VBOX_ONLY_DOCS
    int         cResponseFileArgs     = 0;
    char      **papszResponseFileArgs = NULL;
    char      **papszNewArgv          = NULL;
#endif

    for (int i = 1; i < argc || argc <= iCmd; i++)
    {
        if (    argc <= iCmd
            ||  !strcmp(argv[i], "help")
            ||  !strcmp(argv[i], "--help")
            ||  !strcmp(argv[i], "-?")
            ||  !strcmp(argv[i], "-h")
            ||  !strcmp(argv[i], "-help"))
        {
            if (i >= argc - 1)
            {
                showLogo(g_pStdOut);
                printUsage(USAGE_S_ALL, RTMSGREFENTRYSTR_SCOPE_GLOBAL, g_pStdOut);
                return 0;
            }
            fShowLogo = true;
            fShowHelp = true;
            iCmd++;
            continue;
        }

#ifndef VBOX_ONLY_DOCS
        if (   !strcmp(argv[i], "-V")
            || !strcmp(argv[i], "--version")
            || !strcmp(argv[i], "-v")       /* deprecated */
            || !strcmp(argv[i], "-version") /* deprecated */
            || !strcmp(argv[i], "-Version") /* deprecated */)
        {
            /* Print version number, and do nothing else. */
            RTPrintf("%sr%u\n", VBOX_VERSION_STRING, RTBldCfgRevision());
            return 0;
        }
#endif

        if (   !strcmp(argv[i], "--dumpopts")
            || !strcmp(argv[i], "-dumpopts") /* deprecated */)
        {
            /* Special option to dump really all commands,
             * even the ones not understood on this platform. */
            printUsage(USAGE_S_DUMPOPTS, RTMSGREFENTRYSTR_SCOPE_GLOBAL, g_pStdOut);
            return 0;
        }

        if (   !strcmp(argv[i], "--nologo")
            || !strcmp(argv[i], "-q")
            || !strcmp(argv[i], "-nologo") /* deprecated */)
        {
            /* suppress the logo */
            fShowLogo = false;
            iCmd++;
        }
        else if (   !strcmp(argv[i], "--detailed-progress")
                 || !strcmp(argv[i], "-d"))
        {
            /* detailed progress report */
            g_fDetailedProgress = true;
            iCmd++;
        }
        else if (!strcmp(argv[i], "--settingspw"))
        {
            if (i >= argc - 1)
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Password expected");
            /* password for certain settings */
            pszSettingsPw = argv[i + 1];
            iCmd += 2;
        }
        else if (!strcmp(argv[i], "--settingspwfile"))
        {
            if (i >= argc-1)
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "No password file specified");
            pszSettingsPwFile = argv[i+1];
            iCmd += 2;
        }
#ifndef VBOX_ONLY_DOCS
        else if (argv[i][0] == '@')
        {
            if (papszResponseFileArgs)
                return RTMsgErrorExitFailure("Only one response file allowed");

            /* Load response file, making sure it's valid UTF-8. */
            char  *pszResponseFile;
            size_t cbResponseFile;
            vrc = RTFileReadAllEx(&argv[i][1], 0, RTFOFF_MAX, RTFILE_RDALL_O_DENY_NONE | RTFILE_RDALL_F_TRAILING_ZERO_BYTE,
                                  (void **)&pszResponseFile, &cbResponseFile);
            if (RT_FAILURE(vrc))
                return RTMsgErrorExitFailure("Error reading response file '%s': %Rrc", &argv[i][1], vrc);
            vrc = RTStrValidateEncoding(pszResponseFile);
            if (RT_FAILURE(vrc))
            {
                RTFileReadAllFree(pszResponseFile, cbResponseFile);
                return RTMsgErrorExitFailure("Invalid response file ('%s') encoding: %Rrc", &argv[i][1], vrc);
            }

            /* Parse it. */
            vrc = RTGetOptArgvFromString(&papszResponseFileArgs, &cResponseFileArgs, pszResponseFile,
                                         RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, NULL);
            RTFileReadAllFree(pszResponseFile, cbResponseFile);
            if (RT_FAILURE(vrc))
                return RTMsgErrorExitFailure("Failed to parse response file '%s' (bourne shell style): %Rrc", &argv[i][1], vrc);

            /* Construct new argv+argc with the response file arguments inserted. */
            int cNewArgs = argc + cResponseFileArgs;
            papszNewArgv = (char **)RTMemAllocZ((cNewArgs + 2) * sizeof(papszNewArgv[0]));
            if (!papszNewArgv)
                return RTMsgErrorExitFailure("out of memory");
            memcpy(&papszNewArgv[0], &argv[0], sizeof(argv[0]) * (i + 1));
            memcpy(&papszNewArgv[i + 1], papszResponseFileArgs, sizeof(argv[0]) * cResponseFileArgs);
            memcpy(&papszNewArgv[i + 1 + cResponseFileArgs], &argv[i + 1], sizeof(argv[0]) * (argc - i - 1 + 1));
            argv = papszNewArgv;
            argc = argc + cResponseFileArgs;

            iCmd++;
        }
#endif
        else
            break;
    }

    iCmdArg = iCmd + 1;

    /*
     * Show the logo and lookup the command and deal with fShowHelp = true.
     */
    if (fShowLogo)
        showLogo(g_pStdOut);

#ifndef VBOX_ONLY_DOCS
    PCVBMGCMD pCmd = lookupCommand(argv[iCmd]);
    if (pCmd && pCmd->enmCmdHelp != VBMG_CMD_TODO)
        setCurrentCommand(pCmd->enmCmdHelp);

    if (   pCmd
        && (   fShowHelp
            || (   argc - iCmdArg == 0
                && pCmd->enmHelpCat != USAGE_INVALID)))
    {
        if (pCmd->enmCmdHelp == VBMG_CMD_TODO)
            printUsage(pCmd->enmHelpCat, RTMSGREFENTRYSTR_SCOPE_GLOBAL, g_pStdOut);
        else if (fShowHelp)
            printHelp(g_pStdOut);
        else
            printUsage(g_pStdOut);
        return RTEXITCODE_FAILURE; /* error */
    }
    if (!pCmd)
    {
        if (!strcmp(argv[iCmd], "commands"))
        {
            RTPrintf("commands:\n");
            for (unsigned i = 0; i < RT_ELEMENTS(g_aCommands); i++)
                if (   i == 0  /* skip backwards compatibility entries */
                    || (g_aCommands[i].enmHelpCat != USAGE_S_NEWCMD
                        ? g_aCommands[i].enmHelpCat != g_aCommands[i - 1].enmHelpCat
                        : g_aCommands[i].enmCmdHelp != g_aCommands[i - 1].enmCmdHelp))
                    RTPrintf("    %s\n", g_aCommands[i].pszCommand);
            return RTEXITCODE_SUCCESS;
        }
        return errorSyntax(USAGE_S_ALL, "Invalid command '%s'", argv[iCmd]);
    }

    RTEXITCODE rcExit;
    if (!(pCmd->fFlags & VBMG_CMD_F_NO_COM))
    {
        /*
         * Initialize COM.
         */
        using namespace com;
        HRESULT hrc = com::Initialize();
        if (FAILED(hrc))
        {
# ifdef VBOX_WITH_XPCOM
            if (hrc == NS_ERROR_FILE_ACCESS_DENIED)
            {
                char szHome[RTPATH_MAX] = "";
                com::GetVBoxUserHomeDirectory(szHome, sizeof(szHome));
                return RTMsgErrorExit(RTEXITCODE_FAILURE,
                       "Failed to initialize COM because the global settings directory '%s' is not accessible!", szHome);
            }
# endif
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to initialize COM! (hrc=%Rhrc)", hrc);
        }


        /*
         * Get the remote VirtualBox object and create a local session object.
         */
        rcExit = RTEXITCODE_FAILURE;
        ComPtr<IVirtualBoxClient> virtualBoxClient;
        ComPtr<IVirtualBox> virtualBox;
        hrc = virtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
        if (SUCCEEDED(hrc))
            hrc = virtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam());
        if (SUCCEEDED(hrc))
        {
            ComPtr<ISession> session;
            hrc = session.createInprocObject(CLSID_Session);
            if (SUCCEEDED(hrc))
            {
                /* Session secret. */
                if (pszSettingsPw)
                    CHECK_ERROR2I_STMT(virtualBox, SetSettingsSecret(Bstr(pszSettingsPw).raw()), rcExit = RTEXITCODE_FAILURE);
                else if (pszSettingsPwFile)
                    rcExit = settingsPasswordFile(virtualBox, pszSettingsPwFile);
                else
                    rcExit = RTEXITCODE_SUCCESS;
                if (rcExit == RTEXITCODE_SUCCESS)
                {
                    /*
                     * Call the handler.
                     */
                    HandlerArg handlerArg = { argc - iCmdArg, &argv[iCmdArg], virtualBox, session };
                    rcExit = pCmd->pfnHandler(&handlerArg);

                    /* Although all handlers should always close the session if they open it,
                     * we do it here just in case if some of the handlers contains a bug --
                     * leaving the direct session not closed will turn the machine state to
                     * Aborted which may have unwanted side effects like killing the saved
                     * state file (if the machine was in the Saved state before). */
                    session->UnlockMachine();
                }

                NativeEventQueue::getMainEventQueue()->processEventQueue(0);
            }
            else
            {
                com::ErrorInfo info;
                RTMsgError("Failed to create a session object!");
                if (!info.isFullAvailable() && !info.isBasicAvailable())
                    com::GluePrintRCMessage(hrc);
                else
                    com::GluePrintErrorInfo(info);
            }
        }
        else
        {
            com::ErrorInfo info;
            RTMsgError("Failed to create the VirtualBox object!");
            if (!info.isFullAvailable() && !info.isBasicAvailable())
            {
                com::GluePrintRCMessage(hrc);
                RTMsgError("Most likely, the VirtualBox COM server is not running or failed to start.");
            }
            else
                com::GluePrintErrorInfo(info);
        }

        /*
         * Terminate COM, make sure the virtualBox object has been released.
         */
        virtualBox.setNull();
        virtualBoxClient.setNull();
        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
        com::Shutdown();
    }
    else
    {
        /*
         * The command needs no COM.
         */
        HandlerArg  handlerArg;
        handlerArg.argc = argc - iCmdArg;
        handlerArg.argv = &argv[iCmdArg];
        rcExit = pCmd->pfnHandler(&handlerArg);
    }

    if (papszResponseFileArgs)
    {
        RTGetOptArgvFree(papszResponseFileArgs);
        RTMemFree(papszNewArgv);
    }

    return rcExit;
#else  /* VBOX_ONLY_DOCS */
    return RTEXITCODE_SUCCESS;
#endif /* VBOX_ONLY_DOCS */
}
Example #24
0
/** 
 * Main thread. Starts also the LWIP thread.
 */
int VBoxNetLwipNAT::init()
{
    LogFlowFuncEnter();

    /* virtualbox initialized in super class */
    int rc = ::VBoxNetBaseService::init();
    AssertRCReturn(rc, rc);

    std::string networkName = getNetworkName();
    rc = findNatNetwork(virtualbox, networkName, m_net);
    AssertRCReturn(rc, rc);

    ComEventTypeArray aNetEvents;
    aNetEvents.push_back(VBoxEventType_OnNATNetworkPortForward);
    aNetEvents.push_back(VBoxEventType_OnNATNetworkSetting);
    rc = createNatListener(m_listener, virtualbox, this, aNetEvents);
    AssertRCReturn(rc, rc);


    // resolver changes are reported on vbox but are retrieved from
    // host so stash a pointer for future lookups
    HRESULT hrc = virtualbox->COMGETTER(Host)(m_host.asOutParam());
    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);

    ComEventTypeArray aVBoxEvents;
    aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
    aVBoxEvents.push_back(VBoxEventType_OnNATNetworkStartStop);
    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
    AssertRCReturn(rc, rc);

    BOOL fIPv6Enabled = FALSE;
    hrc = m_net->COMGETTER(IPv6Enabled)(&fIPv6Enabled);
    AssertComRCReturn(hrc, VERR_NOT_FOUND);

    BOOL fIPv6DefaultRoute = FALSE;
    if (fIPv6Enabled)
    {
        hrc = m_net->COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(&fIPv6DefaultRoute);
        AssertComRCReturn(hrc, VERR_NOT_FOUND);
    }

    m_ProxyOptions.ipv6_enabled = fIPv6Enabled;
    m_ProxyOptions.ipv6_defroute = fIPv6DefaultRoute;


    com::Bstr bstrSourceIp4Key = com::BstrFmt("NAT/%s/SourceIp4", networkName.c_str());
    com::Bstr bstrSourceIpX;
    hrc = virtualbox->GetExtraData(bstrSourceIp4Key.raw(), bstrSourceIpX.asOutParam());
    if (SUCCEEDED(hrc))
    {
        RTNETADDRIPV4 addr;
        rc = RTNetStrToIPv4Addr(com::Utf8Str(bstrSourceIpX).c_str(), &addr);
        if (RT_SUCCESS(rc))
        {
            RT_ZERO(m_src4);

            m_src4.sin_addr.s_addr = addr.u;
            m_ProxyOptions.src4 = &m_src4;

            bstrSourceIpX.setNull();
        }
    }

    if (!fDontLoadRulesOnStartup)
    {
        fetchNatPortForwardRules(m_net, false, m_vecPortForwardRule4);
        fetchNatPortForwardRules(m_net, true, m_vecPortForwardRule6);
    } /* if (!fDontLoadRulesOnStartup) */

    AddressToOffsetMapping tmp;
    rc = localMappings(m_net, tmp);
    if (RT_SUCCESS(rc) && tmp.size() != 0)
    {
        unsigned long i = 0;
        for (AddressToOffsetMapping::iterator it = tmp.begin();
             it != tmp.end() && i < RT_ELEMENTS(m_lo2off);
             ++it, ++i)
        {
            ip4_addr_set_u32(&m_lo2off[i].loaddr, it->first.u);
            m_lo2off[i].off = it->second;
        }

        m_loOptDescriptor.lomap = m_lo2off;
        m_loOptDescriptor.num_lomap = i;
        m_ProxyOptions.lomap_desc = &m_loOptDescriptor;
    }

    com::Bstr bstr;
    hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
    AssertComRCReturn(hrc, VERR_NOT_FOUND);
    if (!bstr.isEmpty())
    {
        com::Utf8Str strTftpRoot(com::Utf8StrFmt("%ls%c%s",
                                     bstr.raw(), RTPATH_DELIMITER, "TFTP"));
        char *pszStrTemp;       // avoid const char ** vs char **
        rc = RTStrUtf8ToCurrentCP(&pszStrTemp, strTftpRoot.c_str());
        AssertRC(rc);
        m_ProxyOptions.tftp_root = pszStrTemp;
    }

    m_ProxyOptions.nameservers = getHostNameservers();

    /* end of COM initialization */

    rc = g_pLwipNat->tryGoOnline();
    if (RT_FAILURE(rc))
        return rc;

    /* this starts LWIP thread */
    vboxLwipCoreInitialize(VBoxNetLwipNAT::onLwipTcpIpInit, this);

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Example #25
0
/**
 * @note: this work on Event thread.
 */
HRESULT VBoxNetLwipNAT::HandleEvent(VBoxEventType_T aEventType, IEvent *pEvent)
{
    HRESULT hrc = S_OK;
    switch (aEventType)
    {
        case VBoxEventType_OnNATNetworkSetting:
        {
            ComPtr<INATNetworkSettingEvent> pSettingsEvent(pEvent);

            com::Bstr networkName;
            hrc = pSettingsEvent->COMGETTER(NetworkName)(networkName.asOutParam());
            AssertComRCReturn(hrc, hrc);
            if (networkName.compare(getNetworkName().c_str()))
                break; /* change not for our network */

            // XXX: only handle IPv6 default route for now
            if (!m_ProxyOptions.ipv6_enabled)
                break;

            BOOL fIPv6DefaultRoute = FALSE;
            hrc = pSettingsEvent->COMGETTER(AdvertiseDefaultIPv6RouteEnabled)(&fIPv6DefaultRoute);
            AssertComRCReturn(hrc, hrc);

            if (m_ProxyOptions.ipv6_defroute == fIPv6DefaultRoute)
                break;

            m_ProxyOptions.ipv6_defroute = fIPv6DefaultRoute;
            tcpip_callback_with_block(proxy_rtadvd_do_quick, &m_LwipNetIf, 0);
            break;
        }

        case VBoxEventType_OnNATNetworkPortForward:
        {
            ComPtr<INATNetworkPortForwardEvent> pForwardEvent = pEvent;

            com::Bstr networkName;
            hrc = pForwardEvent->COMGETTER(NetworkName)(networkName.asOutParam());
            AssertComRCReturn(hrc, hrc);
            if (networkName.compare(getNetworkName().c_str()))
                break; /* change not for our network */

            BOOL fCreateFW;
            hrc = pForwardEvent->COMGETTER(Create)(&fCreateFW);
            AssertComRCReturn(hrc, hrc);

            BOOL  fIPv6FW;
            hrc = pForwardEvent->COMGETTER(Ipv6)(&fIPv6FW);
            AssertComRCReturn(hrc, hrc);

            com::Bstr name;
            hrc = pForwardEvent->COMGETTER(Name)(name.asOutParam());
            AssertComRCReturn(hrc, hrc);

            NATProtocol_T proto = NATProtocol_TCP;
            hrc = pForwardEvent->COMGETTER(Proto)(&proto);
            AssertComRCReturn(hrc, hrc);

            com::Bstr strHostAddr;
            hrc = pForwardEvent->COMGETTER(HostIp)(strHostAddr.asOutParam());
            AssertComRCReturn(hrc, hrc);

            LONG lHostPort;
            hrc = pForwardEvent->COMGETTER(HostPort)(&lHostPort);
            AssertComRCReturn(hrc, hrc);

            com::Bstr strGuestAddr;
            hrc = pForwardEvent->COMGETTER(GuestIp)(strGuestAddr.asOutParam());
            AssertComRCReturn(hrc, hrc);

            LONG lGuestPort;
            hrc = pForwardEvent->COMGETTER(GuestPort)(&lGuestPort);
            AssertComRCReturn(hrc, hrc);

            VECNATSERVICEPF& rules = fIPv6FW ? m_vecPortForwardRule6
                                             : m_vecPortForwardRule4;

            NATSEVICEPORTFORWARDRULE r;
            RT_ZERO(r);

            r.Pfr.fPfrIPv6 = fIPv6FW;

            switch (proto)
            {
                case NATProtocol_TCP:
                    r.Pfr.iPfrProto = IPPROTO_TCP;
                    break;
                case NATProtocol_UDP:
                    r.Pfr.iPfrProto = IPPROTO_UDP;
                    break;

                default:
                    LogRel(("Event: %s %s port-forwarding rule \"%s\":"
                            " invalid protocol %d\n",
                            fCreateFW ? "Add" : "Remove",
                            fIPv6FW ? "IPv6" : "IPv4",
                            com::Utf8Str(name).c_str(),
                            (int)proto));
                    goto port_forward_done;
            }

            LogRel(("Event: %s %s port-forwarding rule \"%s\":"
                    " %s %s%s%s:%d -> %s%s%s:%d\n",
                    fCreateFW ? "Add" : "Remove",
                    fIPv6FW ? "IPv6" : "IPv4",
                    com::Utf8Str(name).c_str(),
                    proto == NATProtocol_TCP ? "TCP" : "UDP",
                    /* from */
                    fIPv6FW ? "[" : "",
                    com::Utf8Str(strHostAddr).c_str(),
                    fIPv6FW ? "]" : "",
                    lHostPort,
                    /* to */
                    fIPv6FW ? "[" : "",
                    com::Utf8Str(strGuestAddr).c_str(),
                    fIPv6FW ? "]" : "",
                    lGuestPort));

            if (name.length() > sizeof(r.Pfr.szPfrName))
            {
                hrc = E_INVALIDARG;
                goto port_forward_done;
            }

            RTStrPrintf(r.Pfr.szPfrName, sizeof(r.Pfr.szPfrName),
                        "%s", com::Utf8Str(name).c_str());

            RTStrPrintf(r.Pfr.szPfrHostAddr, sizeof(r.Pfr.szPfrHostAddr),
                        "%s", com::Utf8Str(strHostAddr).c_str());

            /* XXX: limits should be checked */
            r.Pfr.u16PfrHostPort = (uint16_t)lHostPort;

            RTStrPrintf(r.Pfr.szPfrGuestAddr, sizeof(r.Pfr.szPfrGuestAddr),
                        "%s", com::Utf8Str(strGuestAddr).c_str());

            /* XXX: limits should be checked */
            r.Pfr.u16PfrGuestPort = (uint16_t)lGuestPort;

            if (fCreateFW) /* Addition */
            {
                int rc = natServicePfRegister(r);
                if (RT_SUCCESS(rc))
                    rules.push_back(r);
            }
            else /* Deletion */
            {
                ITERATORNATSERVICEPF it;
                for (it = rules.begin(); it != rules.end(); ++it)
                {
                    /* compare */
                    NATSEVICEPORTFORWARDRULE& natFw = *it;
                    if (   natFw.Pfr.iPfrProto == r.Pfr.iPfrProto
                        && natFw.Pfr.u16PfrHostPort == r.Pfr.u16PfrHostPort
                        && (strncmp(natFw.Pfr.szPfrHostAddr, r.Pfr.szPfrHostAddr, INET6_ADDRSTRLEN) == 0)
                        && natFw.Pfr.u16PfrGuestPort == r.Pfr.u16PfrGuestPort
                        && (strncmp(natFw.Pfr.szPfrGuestAddr, r.Pfr.szPfrGuestAddr, INET6_ADDRSTRLEN) == 0))
                    {
                        RTCMemAutoPtr<fwspec> pFwCopy;
                        if (RT_UNLIKELY(!pFwCopy.alloc()))
                            break;

                        memcpy(pFwCopy.get(), &natFw.FWSpec, sizeof(natFw.FWSpec));

                        int status = portfwd_rule_del(pFwCopy.get());
                        if (status != 0)
                            break;

                        pFwCopy.release(); /* owned by lwip thread now */
                        rules.erase(it);
                        break;
                    }
                } /* loop over vector elements */
            } /* condition add or delete */
        port_forward_done:
            /* clean up strings */
            name.setNull();
            strHostAddr.setNull();
            strGuestAddr.setNull();
            break;
        }

        case VBoxEventType_OnHostNameResolutionConfigurationChange:
        {
            const char **ppcszNameServers = getHostNameservers();
            err_t error;

            error = tcpip_callback_with_block(pxdns_set_nameservers,
                                              ppcszNameServers,
                                              /* :block */ 0);
            if (error != ERR_OK && ppcszNameServers != NULL)
                RTMemFree(ppcszNameServers);
            break;
        }

        case VBoxEventType_OnNATNetworkStartStop:
        {
            ComPtr <INATNetworkStartStopEvent> pStartStopEvent = pEvent;

            com::Bstr networkName;
            hrc = pStartStopEvent->COMGETTER(NetworkName)(networkName.asOutParam());
            AssertComRCReturn(hrc, hrc);
            if (networkName.compare(getNetworkName().c_str()))
                break; /* change not for our network */

            BOOL fStart = TRUE;
            hrc = pStartStopEvent->COMGETTER(StartEvent)(&fStart);
            AssertComRCReturn(hrc, hrc);

            if (!fStart)
                shutdown();
            break;
        }
    }
    return hrc;
}
/**
 * Handles the 'bandwidthctl' command.
 * @returns Exit code.
 * @param   a               The handler argument package.
 */
int handleBandwidthControl(HandlerArg *a)
{
    int c = VERR_INTERNAL_ERROR;        /* initialized to shut up gcc */
    HRESULT rc = S_OK;
    ComPtr<IMachine> machine;
    ComPtr<IBandwidthControl> bwCtrl;

    if (a->argc < 2)
        return errorSyntax(USAGE_BANDWIDTHCONTROL, "Too few parameters");
    else if (a->argc > 7)
        return errorSyntax(USAGE_BANDWIDTHCONTROL, "Too many parameters");

    /* try to find the given machine */
    CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
                                               machine.asOutParam()), 1);

    /* open a session for the VM (new or shared) */
    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
    SessionType_T st;
    CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), 1);
    bool fRunTime = (st == SessionType_Shared);

    /* get the mutable session machine */
    a->session->COMGETTER(Machine)(machine.asOutParam());
    rc = machine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam());
    if (FAILED(rc)) goto leave;

    if (!strcmp(a->argv[1], "add"))
    {
        if (fRunTime)
        {
            errorArgument("Bandwidth groups cannot be created while the VM is running\n");
            goto leave;
        }
        rc = handleBandwidthControlAdd(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
    }
    else if (!strcmp(a->argv[1], "remove"))
    {
        if (fRunTime)
        {
            errorArgument("Bandwidth groups cannot be deleted while the VM is running\n");
            goto leave;
        }
        rc = handleBandwidthControlRemove(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
    }
    else if (!strcmp(a->argv[1], "set"))
        rc = handleBandwidthControlSet(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
    else if (!strcmp(a->argv[1], "list"))
        rc = handleBandwidthControlList(a, bwCtrl) == RTEXITCODE_SUCCESS ? S_OK : E_FAIL;
    else
    {
        errorSyntax(USAGE_BANDWIDTHCONTROL, "Invalid parameter '%s'", Utf8Str(a->argv[1]).c_str());
        rc = E_FAIL;
    }

    /* commit changes */
    if (SUCCEEDED(rc))
        CHECK_ERROR(machine, SaveSettings());

leave:
    /* it's important to always close sessions */
    a->session->UnlockMachine();

    return SUCCEEDED(rc) ? 0 : 1;
}
        STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent *aEvent)
        {
            switch (aType)
            {
                case VBoxEventType_OnMachineRegistered:
                {
                    ComPtr<IMachineRegisteredEvent> pEvent = aEvent;
                    Assert(pEvent);

                    Bstr uuid;
                    BOOL fRegistered;
                    HRESULT hr = pEvent->COMGETTER(Registered)(&fRegistered);
                    if (SUCCEEDED(hr))
                        hr = pEvent->COMGETTER(MachineId)(uuid.asOutParam());

                    if (SUCCEEDED(hr))
                    {
                        int rc = RTCritSectEnter(&g_csMachines);
                        if (RT_SUCCESS(rc))
                        {
                            rc = fRegistered
                               ? machineAdd(uuid)
                               : machineRemove(uuid);
                            int rc2 = RTCritSectLeave(&g_csMachines);
                            if (RT_SUCCESS(rc))
                                rc = rc2;
                            AssertRC(rc);
                        }
                    }
                    break;
                }

                case VBoxEventType_OnMachineStateChanged:
                {
                    ComPtr<IMachineStateChangedEvent> pEvent = aEvent;
                    Assert(pEvent);

                    MachineState_T machineState;
                    Bstr uuid;

                    HRESULT hr = pEvent->COMGETTER(State)(&machineState);
                    if (SUCCEEDED(hr))
                        hr = pEvent->COMGETTER(MachineId)(uuid.asOutParam());

                    if (SUCCEEDED(hr))
                    {
                        int rc = RTCritSectEnter(&g_csMachines);
                        if (RT_SUCCESS(rc))
                        {
                            for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
                                if (g_aModules[j].fEnabled)
                                {
                                    int rc2 = g_aModules[j].pDesc->pfnOnMachineStateChanged(uuid,
                                                                                            machineState);
                                    if (RT_FAILURE(rc2))
                                        serviceLog("Module '%s' reported an error: %Rrc\n",
                                                   g_aModules[j].pDesc->pszName, rc);
                                    /* Keep going. */
                                }

                            int rc2 = RTCritSectLeave(&g_csMachines);
                            if (RT_SUCCESS(rc))
                                rc = rc2;
                            AssertRC(rc);
                        }
                    }
                    break;
                }

                case VBoxEventType_OnVBoxSVCAvailabilityChanged:
                {
                    ComPtr<IVBoxSVCAvailabilityChangedEvent> pVSACEv = aEvent;
                    Assert(pVSACEv);
                    BOOL fAvailable = FALSE;
                    pVSACEv->COMGETTER(Available)(&fAvailable);

                    /* First, notify all modules. */
                    for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
                        if (g_aModules[j].fEnabled)
                        {
                            int rc2 = g_aModules[j].pDesc->pfnOnServiceStateChanged(RT_BOOL(fAvailable));
                            if (RT_FAILURE(rc2))
                                serviceLog("Module '%s' reported an error: %Rrc\n",
                                           g_aModules[j].pDesc->pszName, rc2);
                            /* Keep going. */
                        }

                    /* Do global teardown/re-creation stuff. */
                    if (!fAvailable)
                    {
                        serviceLog("VBoxSVC became unavailable\n");
                        watchdogShutdown();
                    }
                    else
                    {
                        serviceLog("VBoxSVC became available\n");
                        int rc2 = watchdogSetup();
                        if (RT_FAILURE(rc2))
                            serviceLog("Unable to re-set up watchdog (rc=%Rrc)!\n", rc2);
                    }

                    break;
                }

                default:
                    /* Not handled event, just skip it. */
                    break;
            }

            return S_OK;
        }
/**
 * Enumerates the properties in the guest property store.
 *
 * @returns 0 on success, 1 on failure
 * @note see the command line API description for parameters
 */
static int handleWaitGuestProperty(HandlerArg *a)
{
    /*
     * Handle arguments
     */
    bool        fFailOnTimeout = false;
    const char *pszPatterns    = NULL;
    uint32_t    cMsTimeout     = RT_INDEFINITE_WAIT;
    bool        usageOK        = true;
    if (a->argc < 2)
        usageOK = false;
    else
        pszPatterns = a->argv[1];
    ComPtr<IMachine> machine;
    HRESULT rc;
    CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
                                           machine.asOutParam()));
    if (!machine)
        usageOK = false;
    for (int i = 2; usageOK && i < a->argc; ++i)
    {
        if (   !strcmp(a->argv[i], "--timeout")
            || !strcmp(a->argv[i], "-timeout"))
        {
            if (   i + 1 >= a->argc
                || RTStrToUInt32Full(a->argv[i + 1], 10, &cMsTimeout) != VINF_SUCCESS)
                usageOK = false;
            else
                ++i;
        }
        else if (!strcmp(a->argv[i], "--fail-on-timeout"))
            fFailOnTimeout = true;
        else
            usageOK = false;
    }
    if (!usageOK)
        return errorSyntax(USAGE_GUESTPROPERTY, "Incorrect parameters");

    /*
     * Set up the event listener and wait until found match or timeout.
     */
    Bstr aMachStrGuid;
    machine->COMGETTER(Id)(aMachStrGuid.asOutParam());
    Guid aMachGuid(aMachStrGuid);
    ComPtr<IEventSource> es;
    CHECK_ERROR(a->virtualBox, COMGETTER(EventSource)(es.asOutParam()));
    ComPtr<IEventListener> listener;
    CHECK_ERROR(es, CreateListener(listener.asOutParam()));
    com::SafeArray <VBoxEventType_T> eventTypes(1);
    eventTypes.push_back(VBoxEventType_OnGuestPropertyChanged);
    CHECK_ERROR(es, RegisterListener(listener, ComSafeArrayAsInParam(eventTypes), false));

    uint64_t u64Started = RTTimeMilliTS();
    bool fSignalled = false;
    do
    {
        unsigned cMsWait;
        if (cMsTimeout == RT_INDEFINITE_WAIT)
            cMsWait = 1000;
        else
        {
            uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
            if (cMsElapsed >= cMsTimeout)
                break; /* timed out */
            cMsWait = RT_MIN(1000, cMsTimeout - (uint32_t)cMsElapsed);
        }

        ComPtr<IEvent> ev;
        rc = es->GetEvent(listener, cMsWait, ev.asOutParam());
        if (ev)
        {
            VBoxEventType_T aType;
            rc = ev->COMGETTER(Type)(&aType);
            switch (aType)
            {
                case VBoxEventType_OnGuestPropertyChanged:
                {
                    ComPtr<IGuestPropertyChangedEvent> gpcev = ev;
                    Assert(gpcev);
                    Bstr aNextStrGuid;
                    gpcev->COMGETTER(MachineId)(aNextStrGuid.asOutParam());
                    if (aMachGuid != Guid(aNextStrGuid))
                        continue;
                    Bstr aNextName;
                    gpcev->COMGETTER(Name)(aNextName.asOutParam());
                    if (RTStrSimplePatternMultiMatch(pszPatterns, RTSTR_MAX,
                                                     Utf8Str(aNextName).c_str(), RTSTR_MAX, NULL))
                    {
                        Bstr aNextValue, aNextFlags;
                        gpcev->COMGETTER(Value)(aNextValue.asOutParam());
                        gpcev->COMGETTER(Flags)(aNextFlags.asOutParam());
                        RTPrintf("Name: %ls, value: %ls, flags: %ls\n",
                                 aNextName.raw(), aNextValue.raw(), aNextFlags.raw());
                        fSignalled = true;
                    }
                    break;
                }
                default:
                     AssertFailed();
            }
        }
    } while (!fSignalled);

    es->UnregisterListener(listener);

    int rcRet = 0;
    if (!fSignalled)
    {
        RTMsgError("Time out or interruption while waiting for a notification.");
        if (fFailOnTimeout)
            rcRet = 2;
    }
    return rcRet;
}
/**
 * Print out progress on the console.
 *
 * This runs the main event queue every now and then to prevent piling up
 * unhandled things (which doesn't cause real problems, just makes things
 * react a little slower than in the ideal case).
 */
HRESULT showProgress(ComPtr<IProgress> progress)
{
    using namespace com;

    AssertReturn(progress.isNotNull(), E_FAIL);

    BOOL fCompleted = FALSE;
    ULONG ulCurrentPercent = 0;
    ULONG ulLastPercent = 0;

    ULONG ulLastOperationPercent = (ULONG)-1;

    ULONG ulLastOperation = (ULONG)-1;
    Bstr bstrOperationDescription;

    NativeEventQueue::getMainEventQueue()->processEventQueue(0);

    ULONG cOperations = 1;
    HRESULT hrc = progress->COMGETTER(OperationCount)(&cOperations);
    if (FAILED(hrc))
    {
        RTStrmPrintf(g_pStdErr, "Progress object failure: %Rhrc\n", hrc);
        RTStrmFlush(g_pStdErr);
        return hrc;
    }

    /*
     * Note: Outputting the progress info to stderr (g_pStdErr) is intentional
     *       to not get intermixed with other (raw) stdout data which might get
     *       written in the meanwhile.
     */

    if (!g_fDetailedProgress)
    {
        RTStrmPrintf(g_pStdErr, "0%%...");
        RTStrmFlush(g_pStdErr);
    }

    /* setup signal handling if cancelable */
    bool fCanceledAlready = false;
    BOOL fCancelable;
    hrc = progress->COMGETTER(Cancelable)(&fCancelable);
    if (FAILED(hrc))
        fCancelable = FALSE;
    if (fCancelable)
    {
        signal(SIGINT,   showProgressSignalHandler);
        signal(SIGTERM,  showProgressSignalHandler);
#ifdef SIGBREAK
        signal(SIGBREAK, showProgressSignalHandler);
#endif
    }

    hrc = progress->COMGETTER(Completed(&fCompleted));
    while (SUCCEEDED(hrc))
    {
        progress->COMGETTER(Percent(&ulCurrentPercent));

        if (g_fDetailedProgress)
        {
            ULONG ulOperation = 1;
            hrc = progress->COMGETTER(Operation)(&ulOperation);
            if (FAILED(hrc))
                break;
            ULONG ulCurrentOperationPercent = 0;
            hrc = progress->COMGETTER(OperationPercent(&ulCurrentOperationPercent));
            if (FAILED(hrc))
                break;

            if (ulLastOperation != ulOperation)
            {
                hrc = progress->COMGETTER(OperationDescription(bstrOperationDescription.asOutParam()));
                if (FAILED(hrc))
                    break;
                ulLastPercent = (ULONG)-1;        // force print
                ulLastOperation = ulOperation;
            }

            if (    ulCurrentPercent != ulLastPercent
                 || ulCurrentOperationPercent != ulLastOperationPercent
               )
            {
                LONG lSecsRem = 0;
                progress->COMGETTER(TimeRemaining)(&lSecsRem);

                RTStrmPrintf(g_pStdErr, "(%u/%u) %ls %02u%% => %02u%% (%d s remaining)\n", ulOperation + 1, cOperations,
                             bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem);
                ulLastPercent = ulCurrentPercent;
                ulLastOperationPercent = ulCurrentOperationPercent;
            }
        }
        else
        {
            /* did we cross a 10% mark? */
            if (ulCurrentPercent / 10  >  ulLastPercent / 10)
            {
                /* make sure to also print out missed steps */
                for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10)
                {
                    if (curVal < 100)
                    {
                        RTStrmPrintf(g_pStdErr, "%u%%...", curVal);
                        RTStrmFlush(g_pStdErr);
                    }
                }
                ulLastPercent = (ulCurrentPercent / 10) * 10;
            }
        }
        if (fCompleted)
            break;

        /* process async cancelation */
        if (g_fCanceled && !fCanceledAlready)
        {
            hrc = progress->Cancel();
            if (SUCCEEDED(hrc))
                fCanceledAlready = true;
            else
                g_fCanceled = false;
        }

        /* make sure the loop is not too tight */
        progress->WaitForCompletion(100);

        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
        hrc = progress->COMGETTER(Completed(&fCompleted));
    }

    /* undo signal handling */
    if (fCancelable)
    {
        signal(SIGINT,   SIG_DFL);
        signal(SIGTERM,  SIG_DFL);
# ifdef SIGBREAK
        signal(SIGBREAK, SIG_DFL);
# endif
    }

    /* complete the line. */
    LONG iRc = E_FAIL;
    hrc = progress->COMGETTER(ResultCode)(&iRc);
    if (SUCCEEDED(hrc))
    {
        if (SUCCEEDED(iRc))
            RTStrmPrintf(g_pStdErr, "100%%\n");
        else if (g_fCanceled)
            RTStrmPrintf(g_pStdErr, "CANCELED\n");
        else
        {
            if (!g_fDetailedProgress)
                RTStrmPrintf(g_pStdErr, "\n");
            RTStrmPrintf(g_pStdErr, "Progress state: %Rhrc\n", iRc);
        }
        hrc = iRc;
    }
    else
    {
        if (!g_fDetailedProgress)
            RTStrmPrintf(g_pStdErr, "\n");
        RTStrmPrintf(g_pStdErr, "Progress object failure: %Rhrc\n", hrc);
    }
    RTStrmFlush(g_pStdErr);
    return hrc;
}
Example #30
0
void HostPowerService::notify(Reason_T aReason)
{
    SessionMachinesList machines;
    VirtualBox::InternalControlList controls;

    HRESULT rc = S_OK;

    switch (aReason)
    {
        case Reason_HostSuspend:
        {
            LogFunc(("SUSPEND\n"));

#ifdef VBOX_WITH_RESOURCE_USAGE_API
            /* Suspend performance sampling to avoid unnecessary callbacks due to jumps in time. */
            PerformanceCollector *perfcollector = mVirtualBox->performanceCollector();

            if (perfcollector)
                perfcollector->suspendSampling();
#endif
            mVirtualBox->getOpenedMachines(machines, &controls);

            /* pause running VMs */
            for (VirtualBox::InternalControlList::const_iterator it = controls.begin();
                 it != controls.end();
                 ++it)
            {
                ComPtr<IInternalSessionControl> pControl = *it;

                /* PauseWithReason() will simply return a failure if
                 * the VM is in an inappropriate state */
                rc = pControl->PauseWithReason(Reason_HostSuspend);
                if (FAILED(rc))
                    continue;

                /* save the control to un-pause the VM later */
                mSessionControls.push_back(pControl);
            }

            LogFunc(("Suspended %d VMs\n", mSessionControls.size()));

            break;
        }

        case Reason_HostResume:
        {
            LogFunc(("RESUME\n"));

            size_t resumed = 0;

            /* go through VMs we paused on Suspend */
            for (size_t i = 0; i < mSessionControls.size(); ++i)
            {
                /* note that Resume() will simply return a failure if the VM is
                 * in an inappropriate state (it will also fail if the VM has
                 * been somehow closed by this time already so that the
                 * console reference we have is dead) */
                rc = mSessionControls[i]->ResumeWithReason(Reason_HostResume);
                if (FAILED(rc))
                    continue;

                ++resumed;
            }

            LogFunc(("Resumed %d VMs\n", resumed));

#ifdef VBOX_WITH_RESOURCE_USAGE_API
            /* Resume the performance sampling. */
            PerformanceCollector *perfcollector = mVirtualBox->performanceCollector();

            if (perfcollector)
                perfcollector->resumeSampling();
#endif

            mSessionControls.clear();

            break;
        }

        case Reason_HostBatteryLow:
        {
            LogFunc(("BATTERY LOW\n"));

            mVirtualBox->getOpenedMachines(machines, &controls);

            size_t saved = 0;

            /* save running VMs */
            for (VirtualBox::InternalControlList::const_iterator it = controls.begin();
                 it != controls.end();
                 ++it)
            {
                ComPtr<IInternalSessionControl> pControl = *it;

                ComPtr<IProgress> progress;

                /* note that SaveStateWithReason() will simply return a failure
                 * if the VM is in an inappropriate state */
                rc = pControl->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());
                if (FAILED(rc))
                    continue;

                /* Wait until the operation has been completed. */
                rc = progress->WaitForCompletion(-1);
                if (SUCCEEDED(rc))
                {
                    LONG iRc;
                    progress->COMGETTER(ResultCode)(&iRc);
                    rc = iRc;
                }

                AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %Rhrc (%#08X)\n", rc, rc));

                if (SUCCEEDED(rc))
                    ++saved;
            }

            LogFunc(("Saved %d VMs\n", saved));

            break;
        }

        default:
            /* nothing */;
    }
}