VirtualBox

Changeset 84554 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
May 27, 2020 8:16:59 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
138284
Message:

Guest Control/Main: Implemented host side support for gracefully rebooting / shutting down the guest. Untested. bugref:9320

Location:
trunk/src/VBox/Main/src-client
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r83323 r84554  
    490490                         tr("Could not find sessions with name '%s'"),
    491491                         aSessionName.c_str());
     492#endif /* VBOX_WITH_GUEST_CONTROL */
     493}
     494
     495HRESULT Guest::shutdown(const std::vector<GuestShutdownFlag_T> &aFlags)
     496{
     497#ifndef VBOX_WITH_GUEST_CONTROL
     498    ReturnComNotImplemented();
     499#else /* VBOX_WITH_GUEST_CONTROL */
     500
     501    /* Validate flags. */
     502    uint32_t fFlags = GuestShutdownFlag_None;
     503    if (aFlags.size())
     504        for (size_t i = 0; i < aFlags.size(); ++i)
     505            fFlags |= aFlags[i];
     506
     507    const uint32_t fValidFlags = GuestShutdownFlag_None | GuestShutdownFlag_PowerOff | GuestShutdownFlag_Reboot;
     508    if (fFlags & ~fValidFlags)
     509        return setError(E_INVALIDARG,tr("Unknown flags: flags value %#x, invalid: %#x"), fFlags, fFlags & ~fValidFlags);
     510
     511    if (   (fFlags & GuestShutdownFlag_PowerOff)
     512        && (fFlags & GuestShutdownFlag_Reboot))
     513        return setError(E_INVALIDARG, tr("Invalid combination of flags (%#x)"), fFlags);
     514
     515    /*
     516     * Create an anonymous session. This is required to run shutting down / rebooting
     517     * the guest with administrative rights.
     518     */
     519    GuestSessionStartupInfo startupInfo;
     520    startupInfo.mName = "Shutting down guest";
     521
     522    GuestCredentials guestCreds;
     523
     524    HRESULT hrc;
     525    ComObjPtr<GuestSession> pSession;
     526    int vrc = i_sessionCreate(startupInfo, guestCreds, pSession);
     527    if (RT_SUCCESS(vrc))
     528    {
     529        Assert(!pSession.isNull());
     530
     531        int rcGuest = VERR_GSTCTL_GUEST_ERROR;
     532        vrc = pSession->i_startSession(&rcGuest);
     533        if (RT_SUCCESS(vrc))
     534        {
     535            vrc = pSession->i_shutdown(fFlags, &rcGuest);
     536            if (RT_FAILURE(vrc))
     537            {
     538                switch (vrc)
     539                {
     540                    case VERR_NOT_SUPPORTED:
     541                        hrc = setErrorBoth(VBOX_E_NOT_SUPPORTED, vrc,
     542                                           tr("Shutting down not supported by installed Guest Additions"), vrc);
     543                        break;
     544
     545                    default:
     546                    {
     547                        if (vrc == VERR_GSTCTL_GUEST_ERROR)
     548                            vrc = rcGuest;
     549                        hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not shut down guest: %Rrc"), vrc);
     550                        break;
     551                    }
     552                }
     553            }
     554        }
     555        else
     556        {
     557            if (vrc == VERR_GSTCTL_GUEST_ERROR)
     558                vrc = rcGuest;
     559            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not open guest session: %Rrc"), vrc);
     560        }
     561    }
     562    else
     563    {
     564        switch (vrc)
     565        {
     566            case VERR_MAX_PROCS_REACHED:
     567                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Maximum number of concurrent guest sessions (%d) reached"),
     568                                  VBOX_GUESTCTRL_MAX_SESSIONS);
     569                break;
     570
     571            /** @todo Add more errors here. */
     572
     573           default:
     574                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not create guest session: %Rrc"), vrc);
     575                break;
     576        }
     577    }
     578
     579    LogFlowFunc(("Returning hrc=%Rhrc\n", hrc));
     580    return hrc;
    492581#endif /* VBOX_WITH_GUEST_CONTROL */
    493582}
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r84343 r84554  
    27072707
    27082708/**
     2709 * Shuts down (and optionally powers off / reboots) the guest.
     2710 * Needs supported Guest Additions installed.
     2711 *
     2712 * @returns VBox status code. VERR_NOT_SUPPORTED if not supported by Guest Additions.
     2713 * @param  fFlags               Guest shutdown flags.
     2714 * @param  prcGuest             Guest rc, when returning VERR_GSTCTL_GUEST_ERROR.
     2715 *                              Any other return code indicates some host side error.
     2716 */
     2717int GuestSession::i_shutdown(uint32_t fFlags, int *prcGuest)
     2718{
     2719    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     2720
     2721    AssertPtrReturn(mParent, VERR_INVALID_POINTER);
     2722    if (!(mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_SHUTDOWN))
     2723        return VERR_NOT_SUPPORTED;
     2724
     2725    LogRel(("Guest Control: Shutting down guest (flags = %#x) ...\n", fFlags));
     2726
     2727    GuestWaitEvent *pEvent = NULL;
     2728    int vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
     2729    if (RT_FAILURE(vrc))
     2730        return vrc;
     2731
     2732    /* Prepare HGCM call. */
     2733    VBOXHGCMSVCPARM paParms[2];
     2734    int i = 0;
     2735    HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
     2736    HGCMSvcSetU32(&paParms[i++], fFlags);
     2737
     2738    alock.release(); /* Drop write lock before sending. */
     2739
     2740    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     2741
     2742    vrc = i_sendMessage(HOST_MSG_SHUTDOWN, i, paParms);
     2743    if (RT_SUCCESS(vrc))
     2744    {
     2745        vrc = pEvent->Wait(30 * 1000);
     2746        if (RT_FAILURE(vrc))
     2747        {
     2748            if (vrc == VERR_GSTCTL_GUEST_ERROR)
     2749                rcGuest = pEvent->GuestResult();
     2750        }
     2751    }
     2752
     2753    if (RT_FAILURE(vrc))
     2754    {
     2755        LogRel(("Guest Control: Shutting down guest failed, rc=%Rrc\n",
     2756                vrc == VERR_GSTCTL_GUEST_ERROR ? rcGuest : vrc));
     2757
     2758        if (   vrc == VERR_GSTCTL_GUEST_ERROR
     2759            && prcGuest)
     2760            *prcGuest = rcGuest;
     2761    }
     2762
     2763    unregisterWaitEvent(pEvent);
     2764
     2765    LogFlowFuncLeaveRC(vrc);
     2766    return vrc;
     2767}
     2768
     2769/**
    27092770 * Determines the protocol version (sets mData.mProtocolVersion).
    27102771 *
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette