Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 84551)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 84554)
@@ -11790,4 +11790,23 @@
 
   <enum
+    name="GuestShutdownFlag"
+    uuid="587309CD-DDDA-4619-82B0-4B764D9D3BC1"
+  >
+    <desc>
+      Guest shutdown flags.
+    </desc>
+
+    <const name="None"                      value="0">
+      <desc>No flag set.</desc>
+    </const>
+    <const name="PowerOff"                  value="1">
+      <desc>Performs a reboot after shutdown.</desc>
+    </const>
+    <const name="Reboot"                    value="2">
+      <desc>Performs a reboot after shutdown.</desc>
+    </const>
+  </enum>
+
+  <enum
     name="GuestSessionStatus"
     uuid="ac2669da-4624-44f2-85b5-0b0bfb8d8673"
@@ -15052,5 +15071,5 @@
   <interface
     name="IGuest" extends="$unknown"
-    uuid="13a11514-402e-022e-6180-c3944de3f9c8"
+    uuid="00892186-A4AF-4627-B21F-FC561CE4473C"
     wsmap="managed"
     reservedMethods="8" reservedAttributes="16"
@@ -15319,4 +15338,26 @@
         <desc>
           Array with all guest sessions found matching the name specified.
+        </desc>
+      </param>
+    </method>
+
+    <method name="shutdown">
+      <desc>
+        Shuts down (and optionally halts and/or reboots) the guest.
+        Needs supported Guest Additions installed.
+
+        <result name="VBOX_E_NOT_SUPPORTED">
+          Guest OS is not supported for shutting down, or the
+          already installed Guest Additions are not supported.
+        </result>
+
+        <result name="VBOX_E_IPRT_ERROR">
+          Error while shutting down.
+        </result>
+
+      </desc>
+      <param name="flags" type="GuestShutdownFlag" dir="in" safearray="yes">
+        <desc>
+          <link to="GuestShutdownFlag"/> flags.
         </desc>
       </param>
Index: trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestImpl.h	(revision 84551)
+++ trunk/src/VBox/Main/include/GuestImpl.h	(revision 84554)
@@ -173,4 +173,5 @@
      HRESULT findSession(const com::Utf8Str &aSessionName,
                          std::vector<ComPtr<IGuestSession> > &aSessions);
+     HRESULT shutdown(const std::vector<GuestShutdownFlag_T> &aFlags);
      HRESULT updateGuestAdditions(const com::Utf8Str &aSource,
                                   const std::vector<com::Utf8Str> &aArguments,
Index: trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 84551)
+++ trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 84554)
@@ -338,4 +338,5 @@
     int                     i_setSessionStatus(GuestSessionStatus_T sessionStatus, int sessionRc);
     int                     i_signalWaiters(GuestSessionWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS */);
+    int                     i_shutdown(uint32_t fFlags, int *prcGuest);
     int                     i_determineProtocolVersion(void);
     int                     i_waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestSessionWaitResult_T &waitResult, int *pGuestRc);
Index: trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 84551)
+++ trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 84554)
@@ -490,4 +490,93 @@
                          tr("Could not find sessions with name '%s'"),
                          aSessionName.c_str());
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+HRESULT Guest::shutdown(const std::vector<GuestShutdownFlag_T> &aFlags)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_GUEST_CONTROL */
+
+    /* Validate flags. */
+    uint32_t fFlags = GuestShutdownFlag_None;
+    if (aFlags.size())
+        for (size_t i = 0; i < aFlags.size(); ++i)
+            fFlags |= aFlags[i];
+
+    const uint32_t fValidFlags = GuestShutdownFlag_None | GuestShutdownFlag_PowerOff | GuestShutdownFlag_Reboot;
+    if (fFlags & ~fValidFlags)
+        return setError(E_INVALIDARG,tr("Unknown flags: flags value %#x, invalid: %#x"), fFlags, fFlags & ~fValidFlags);
+
+    if (   (fFlags & GuestShutdownFlag_PowerOff)
+        && (fFlags & GuestShutdownFlag_Reboot))
+        return setError(E_INVALIDARG, tr("Invalid combination of flags (%#x)"), fFlags);
+
+    /*
+     * Create an anonymous session. This is required to run shutting down / rebooting
+     * the guest with administrative rights.
+     */
+    GuestSessionStartupInfo startupInfo;
+    startupInfo.mName = "Shutting down guest";
+
+    GuestCredentials guestCreds;
+
+    HRESULT hrc;
+    ComObjPtr<GuestSession> pSession;
+    int vrc = i_sessionCreate(startupInfo, guestCreds, pSession);
+    if (RT_SUCCESS(vrc))
+    {
+        Assert(!pSession.isNull());
+
+        int rcGuest = VERR_GSTCTL_GUEST_ERROR;
+        vrc = pSession->i_startSession(&rcGuest);
+        if (RT_SUCCESS(vrc))
+        {
+            vrc = pSession->i_shutdown(fFlags, &rcGuest);
+            if (RT_FAILURE(vrc))
+            {
+                switch (vrc)
+                {
+                    case VERR_NOT_SUPPORTED:
+                        hrc = setErrorBoth(VBOX_E_NOT_SUPPORTED, vrc,
+                                           tr("Shutting down not supported by installed Guest Additions"), vrc);
+                        break;
+
+                    default:
+                    {
+                        if (vrc == VERR_GSTCTL_GUEST_ERROR)
+                            vrc = rcGuest;
+                        hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not shut down guest: %Rrc"), vrc);
+                        break;
+                    }
+                }
+            }
+        }
+        else
+        {
+            if (vrc == VERR_GSTCTL_GUEST_ERROR)
+                vrc = rcGuest;
+            hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not open guest session: %Rrc"), vrc);
+        }
+    }
+    else
+    {
+        switch (vrc)
+        {
+            case VERR_MAX_PROCS_REACHED:
+                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Maximum number of concurrent guest sessions (%d) reached"),
+                                  VBOX_GUESTCTRL_MAX_SESSIONS);
+                break;
+
+            /** @todo Add more errors here. */
+
+           default:
+                hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Could not create guest session: %Rrc"), vrc);
+                break;
+        }
+    }
+
+    LogFlowFunc(("Returning hrc=%Rhrc\n", hrc));
+    return hrc;
 #endif /* VBOX_WITH_GUEST_CONTROL */
 }
Index: trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 84551)
+++ trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 84554)
@@ -2707,4 +2707,65 @@
 
 /**
+ * Shuts down (and optionally powers off / reboots) the guest.
+ * Needs supported Guest Additions installed.
+ *
+ * @returns VBox status code. VERR_NOT_SUPPORTED if not supported by Guest Additions.
+ * @param  fFlags               Guest shutdown flags.
+ * @param  prcGuest             Guest rc, when returning VERR_GSTCTL_GUEST_ERROR.
+ *                              Any other return code indicates some host side error.
+ */
+int GuestSession::i_shutdown(uint32_t fFlags, int *prcGuest)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    AssertPtrReturn(mParent, VERR_INVALID_POINTER);
+    if (!(mParent->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_SHUTDOWN))
+        return VERR_NOT_SUPPORTED;
+
+    LogRel(("Guest Control: Shutting down guest (flags = %#x) ...\n", fFlags));
+
+    GuestWaitEvent *pEvent = NULL;
+    int vrc = registerWaitEvent(mData.mSession.mID, mData.mObjectID, &pEvent);
+    if (RT_FAILURE(vrc))
+        return vrc;
+
+    /* Prepare HGCM call. */
+    VBOXHGCMSVCPARM paParms[2];
+    int i = 0;
+    HGCMSvcSetU32(&paParms[i++], pEvent->ContextID());
+    HGCMSvcSetU32(&paParms[i++], fFlags);
+
+    alock.release(); /* Drop write lock before sending. */
+
+    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
+
+    vrc = i_sendMessage(HOST_MSG_SHUTDOWN, i, paParms);
+    if (RT_SUCCESS(vrc))
+    {
+        vrc = pEvent->Wait(30 * 1000);
+        if (RT_FAILURE(vrc))
+        {
+            if (vrc == VERR_GSTCTL_GUEST_ERROR)
+                rcGuest = pEvent->GuestResult();
+        }
+    }
+
+    if (RT_FAILURE(vrc))
+    {
+        LogRel(("Guest Control: Shutting down guest failed, rc=%Rrc\n",
+                vrc == VERR_GSTCTL_GUEST_ERROR ? rcGuest : vrc));
+
+        if (   vrc == VERR_GSTCTL_GUEST_ERROR
+            && prcGuest)
+            *prcGuest = rcGuest;
+    }
+
+    unregisterWaitEvent(pEvent);
+
+    LogFlowFuncLeaveRC(vrc);
+    return vrc;
+}
+
+/**
  * Determines the protocol version (sets mData.mProtocolVersion).
  *
