Index: /trunk/src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 15761)
+++ /trunk/src/VBox/Main/ConsoleImpl.cpp	(revision 15762)
@@ -38,4 +38,6 @@
 
 #include "ConsoleImpl.h"
+
+#include "Global.h"
 #include "GuestImpl.h"
 #include "KeyboardImpl.h"
@@ -1352,7 +1354,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState != MachineState_Running &&
-        mMachineState != MachineState_Paused &&
-        mMachineState != MachineState_Stuck)
+    if (!Global::IsActive (mMachineState))
     {
         /* extra nice error message for a common case */
@@ -1392,7 +1392,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState != MachineState_Running &&
-        mMachineState != MachineState_Paused &&
-        mMachineState != MachineState_Stuck)
+    if (!Global::IsActive (mMachineState))
     {
         /* extra nice error message for a common case */
@@ -1456,7 +1454,6 @@
 
     if (mMachineState != MachineState_Running)
-        return setError(VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot reset the machine as it is not running "
-            "(machine state: %d)"), mMachineState);
+        return setError (VBOX_E_INVALID_VM_STATE,
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1488,6 +1485,5 @@
     if (mMachineState != MachineState_Running)
         return setError (VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot pause the machine as it is not running "
-            "(machine state: %d)"), mMachineState);
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1560,6 +1556,5 @@
     if (mMachineState != MachineState_Running)
         return setError (VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot power off the machine as it is not running "
-                "(machine state: %d)"), mMachineState);
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1599,5 +1594,6 @@
 
     if (mMachineState != MachineState_Running)
-        return E_FAIL;
+        return setError (VBOX_E_INVALID_VM_STATE,
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1642,6 +1638,5 @@
     if (mMachineState != MachineState_Running)
         return setError (VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot get guest ACPI mode as it is "
-            "not running (machine state: %d)"), mMachineState);
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1677,6 +1672,5 @@
     if (mMachineState != MachineState_Running)
         return setError (VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot send the sleep button event as it is "
-            "not running (machine state: %d)"), mMachineState);
+            tr ("Invalid machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -1720,5 +1714,5 @@
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Cannot save the execution state as the machine "
-                "is not running (machine state: %d)"), mMachineState);
+                "is not running or paused (machine state: %d)"), mMachineState);
     }
 
@@ -1987,25 +1981,9 @@
     AutoWriteLock alock (this);
 
-    /// @todo (r=dmik) is it legal to attach USB devices when the machine is
-    //  Paused, Starting, Saving, Stopping, etc? if not, we should make a
-    //  stricter check (mMachineState != MachineState_Running).
-    //
-    //  I'm changing it to the semi-strict check for the time being. We'll
-    //  consider the below later.
-    //
-    /* bird: It is not permitted to attach or detach while the VM is saving,
-     * is restoring or has stopped - definitely not.
-     *
-     * Attaching while starting, well, if you don't create any deadlock it
-     * should work...  Paused should work I guess, but we shouldn't push our
-     * luck if we're pausing because an runtime error condition was raised
-     * (which is one of the reasons there better be a separate state for that
-     * in the VMM).
-     */
     if (mMachineState != MachineState_Running &&
         mMachineState != MachineState_Paused)
         return setError (VBOX_E_INVALID_VM_STATE,
-            tr ("Cannot attach a USB device to the machine which is not running "
-                "(machine state: %d)"), mMachineState);
+            tr ("Cannot attach a USB device to the machine which is not "
+                "running or paused (machine state: %d)"), mMachineState);
 
     /* protect mpVM */
@@ -2241,5 +2219,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState > MachineState_Paused)
+    if (Global::IsTransient (mMachineState))
     {
         return setError (VBOX_E_INVALID_VM_STATE,
@@ -2410,5 +2388,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mMachineState))
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Cannot discard a snapshot of the running machine "
@@ -2431,5 +2409,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mMachineState))
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Cannot discard the current state of the running machine "
@@ -2452,5 +2430,5 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mMachineState))
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Cannot discard the current snapshot and state of the "
@@ -4248,7 +4226,7 @@
     AutoWriteLock alock (this);
 
-    if (mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mMachineState))
         return setError(VBOX_E_INVALID_VM_STATE,
-            tr ("Virtual machine is already running "
+            tr ("Virtual machine is already running or busy "
             "(machine state: %d)"), mMachineState);
 
@@ -4910,16 +4888,16 @@
         if (aUpdateServer)
         {
-            /*
-             *  Server notification MUST be done from under the lock; otherwise
-             *  the machine state here and on the server might go out of sync, that
-             *  can lead to various unexpected results (like the machine state being
-             *  >= MachineState_Running on the server, while the session state is
-             *  already SessionState_Closed at the same time there).
+            /* Server notification MUST be done from under the lock; otherwise
+             * the machine state here and on the server might go out of sync
+             * whihc can lead to various unexpected results (like the machine
+             * state being >= MachineState_Running on the server, while the
+             * session state is already SessionState_Closed at the same time
+             * there).
              *
-             *  Cross-lock conditions should be carefully watched out: calling
-             *  UpdateState we will require Machine and SessionMachine locks
-             *  (remember that here we're holding the Console lock here, and
-             *  also all locks that have been entered by the thread before calling
-             *  this method).
+             * Cross-lock conditions should be carefully watched out: calling
+             * UpdateState we will require Machine and SessionMachine locks
+             * (remember that here we're holding the Console lock here, and also
+             * all locks that have been entered by the thread before calling
+             * this method).
              */
             LogFlowThisFunc (("Doing mControl->UpdateState()...\n"));
@@ -5441,5 +5419,5 @@
 
             /* Guru respects only running VMs */
-            Assert ((that->mMachineState >= MachineState_Running));
+            Assert (Global::IsOnline (that->mMachineState));
 
             that->setMachineState (MachineState_Stuck);
Index: /trunk/src/VBox/Main/DisplayImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/DisplayImpl.cpp	(revision 15761)
+++ /trunk/src/VBox/Main/DisplayImpl.cpp	(revision 15762)
@@ -205,5 +205,5 @@
     if (machineState == MachineState_Running)
     {
-        LogFlowFunc (("Machine running\n"));
+        LogFlowFunc (("Machine is running.\n"));
 
         mfMachineRunning = true;
Index: /trunk/src/VBox/Main/MachineDebuggerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineDebuggerImpl.cpp	(revision 15761)
+++ /trunk/src/VBox/Main/MachineDebuggerImpl.cpp	(revision 15762)
@@ -23,4 +23,6 @@
 
 #include "MachineDebuggerImpl.h"
+
+#include "Global.h"
 #include "ConsoleImpl.h"
 #include "Logging.h"
@@ -799,7 +801,5 @@
         MachineState_T machineState;
         mParent->COMGETTER(State) (&machineState);
-        if (    machineState != MachineState_Running
-            &&  machineState != MachineState_Paused
-            &&  machineState != MachineState_Stuck)
+        if (!Global::IsActive (machineState))
             // queue the request
             return true;
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 15761)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 15762)
@@ -670,5 +670,5 @@
                              (SessionMachine *) mData->mSession.mMachine));
 
-        if (mData->mMachineState >= MachineState_Running)
+        if (Global::IsOnlineOrTransient (mData->mMachineState))
         {
             LogWarningThisFunc (("Setting state to Aborted!\n"));
@@ -1945,5 +1945,5 @@
     AssertReturn (mData->mMachineState != MachineState_Saved, E_FAIL);
 
-    if (mData->mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mData->mMachineState))
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Invalid machine state: %d"), mData->mMachineState);
@@ -2265,5 +2265,5 @@
     AssertReturn (mData->mMachineState != MachineState_Saved, E_FAIL);
 
-    if (mData->mMachineState >= MachineState_Running)
+    if (Global::IsOnlineOrTransient (mData->mMachineState))
         return setError (VBOX_E_INVALID_VM_STATE,
             tr ("Invalid machine state: %d"), mData->mMachineState);
@@ -3396,6 +3396,6 @@
             mUserData->mName.raw());
 
-    /* may not be Running */
-    AssertReturn (mData->mMachineState < MachineState_Running, E_FAIL);
+    /* may not be busy */
+    AssertReturn (!Global::IsOnlineOrTransient (mData->mMachineState), E_FAIL);
 
     /* get the session PID */
@@ -3603,6 +3603,6 @@
             mUserData->mName.raw());
 
-    /* may not be Running */
-    AssertReturn (mData->mMachineState < MachineState_Running, E_FAIL);
+    /* may not be busy */
+    AssertReturn (!Global::IsOnlineOrTransient (mData->mMachineState), E_FAIL);
 
     /* get the path to the executable */
@@ -7553,6 +7553,5 @@
     AssertReturnVoid (aThat->mType == IsSnapshotMachine);
 
-    AssertReturnVoid (mData->mMachineState < MachineState_Running ||
-                      mData->mMachineState >= MachineState_Discarding);
+    AssertReturnVoid (!Global::IsOnline (mData->mMachineState));
 
     mHWData.assignCopy (aThat->mHWData);
@@ -7937,6 +7936,6 @@
     if (aReason == Uninit::Abnormal)
     {
-        LogWarningThisFunc (("ABNORMAL client termination! (wasRunning=%d)\n",
-                             lastState >= MachineState_Running));
+        LogWarningThisFunc (("ABNORMAL client termination! (wasBusy=%d)\n",
+                             Global::IsOnlineOrTransient (lastState)));
 
         /* reset the state to Aborted */
@@ -7965,5 +7964,5 @@
 #ifdef VBOX_WITH_USB
     /* release all captured USB devices */
-    if (aReason == Uninit::Abnormal && lastState >= MachineState_Running)
+    if (aReason == Uninit::Abnormal && Global::IsOnline (lastState))
     {
         /* Console::captureUSBDevices() is called in the VM process only after
@@ -8481,5 +8480,5 @@
     AutoMultiWriteLock2 alock (mParent, this);
 
-    AssertReturn ((mData->mMachineState < MachineState_Running ||
+    AssertReturn ((!Global::IsOnlineOrTransient (mData->mMachineState) ||
                    mData->mMachineState == MachineState_Paused) &&
                   mSnapshotData.mLastState == MachineState_Null &&
@@ -8667,5 +8666,5 @@
     AutoMultiWriteLock2 alock (mParent, this);
 
-    ComAssertRet (mData->mMachineState < MachineState_Running, E_FAIL);
+    ComAssertRet (!Global::IsOnlineOrTransient (mData->mMachineState), E_FAIL);
 
     ComObjPtr <Snapshot> snapshot;
@@ -8749,5 +8748,5 @@
     AutoWriteLock alock (this);
 
-    ComAssertRet (mData->mMachineState < MachineState_Running, E_FAIL);
+    ComAssertRet (!Global::IsOnlineOrTransient (mData->mMachineState), E_FAIL);
 
     if (mData->mCurrentSnapshot.isNull())
@@ -8813,5 +8812,5 @@
     AutoWriteLock alock (this);
 
-    ComAssertRet (mData->mMachineState < MachineState_Running, E_FAIL);
+    ComAssertRet (!Global::IsOnlineOrTransient (mData->mMachineState), E_FAIL);
 
     if (mData->mCurrentSnapshot.isNull())
@@ -9509,5 +9508,5 @@
 
         int opFlags = SaveSS_AddOp | SaveSS_CurrentId;
-        if (mSnapshotData.mLastState < MachineState_Running)
+        if (!Global::IsOnline (mSnapshotData.mLastState))
         {
             /* the machine was powered off or saved when taking a snapshot, so
@@ -9522,5 +9521,5 @@
     if (aSuccess && SUCCEEDED (rc))
     {
-        bool online = mSnapshotData.mLastState >= MachineState_Running;
+        bool online = Global::IsOnline (mSnapshotData.mLastState);
 
         /* associate old hard disks with the snapshot and do locking/unlocking*/
@@ -9594,5 +9593,5 @@
     HRESULT rc = S_OK;
 
-    bool online = mSnapshotData.mLastState >= MachineState_Running;
+    bool online = Global::IsOnline (mSnapshotData.mLastState);
 
     LogFlowThisFunc (("Creating differencing hard disks (online=%d)...\n",
Index: /trunk/src/VBox/Main/USBControllerImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/USBControllerImpl.cpp	(revision 15761)
+++ /trunk/src/VBox/Main/USBControllerImpl.cpp	(revision 15762)
@@ -20,7 +20,7 @@
  */
 
-
-
 #include "USBControllerImpl.h"
+
+#include "Global.h"
 #include "MachineImpl.h"
 #include "VirtualBoxImpl.h"
@@ -456,5 +456,5 @@
 
     /* notify the proxy (only when it makes sense) */
-    if (filter->data().mActive && adep.machineState() >= MachineState_Running)
+    if (filter->data().mActive && Global::IsOnline (adep.machineState()))
     {
         USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
@@ -520,5 +520,5 @@
 
     /* notify the proxy (only when it makes sense) */
-    if (filter->data().mActive && adep.machineState() >= MachineState_Running)
+    if (filter->data().mActive && Global::IsOnline (adep.machineState()))
     {
         USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
@@ -846,6 +846,5 @@
                 /* notify the proxy (only when it makes sense) */
                 if ((*it)->data().mActive &&
-                    adep.machineState() >= MachineState_Running &&
-                    adep.machineState() < MachineState_Discarding)
+                    Global::IsOnline (adep.machineState()))
                 {
                     USBDeviceFilter *filter = *it;
@@ -860,6 +859,5 @@
         }
 
-        if (adep.machineState() >= MachineState_Running &&
-            adep.machineState() < MachineState_Discarding)
+        if (Global::IsOnline (adep.machineState()))
         {
             /* find all removed old filters (absent in the new list)
@@ -1034,6 +1032,5 @@
     AssertComRCReturnVoid (adep.rc());
     /* Machine::copyFrom() may not be called when the VM is running */
-    AssertReturnVoid (adep.machineState() < MachineState_Running ||
-                      adep.machineState() >= MachineState_Discarding);
+    AssertReturnVoid (!Global::IsOnline (adep.machineState()));
 
     /* peer is not modified, lock it for reading (aThat is "master" so locked
@@ -1083,5 +1080,5 @@
 
     /* nothing to do if the machine isn't running */
-    if (adep.machineState() < MachineState_Running)
+    if (!Global::IsOnline (adep.machineState()))
         return S_OK;
 
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 15761)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 15762)
@@ -482,4 +482,15 @@
       an offline state. This inconsistency may be removed in one of the future
       versions of VirtualBox by adding a new state.
+
+      <note internal="yes">
+        For whoever decides to touch this enum: In order to keep the
+        comparisons involving FirstOnline and LastOnline pseudo-states valid,
+        the numeric values of these states must be correspondingly updated if
+        needed: for any online VM state, the condition
+        <tt>FirstOnline &lt;= state &lt;= LastOnline</tt> must be
+        <tt>true</tt>. The same relates to transient states for which
+        the condition <tt>FirstOnline &lt;= state &lt;= LastOnline</tt> must be
+        <tt>true</tt>.
+      </note>
     </desc>
 
@@ -508,5 +519,5 @@
         <note internal="yes">
           For whoever decides to touch this enum: In order to keep the
-          comparisons in the source code valid, this state must immediately
+          comparisons in the old source code valid, this state must immediately
           precede the Paused state.
         </note>
@@ -518,5 +529,5 @@
         <note internal="yes">
           For whoever decides to touch this enum: In order to keep the
-          comparisons in the source code valid, this state must immediately
+          comparisons in the old source code valid, this state must immediately
           follow the Running state.
         </note>
@@ -567,12 +578,4 @@
       <desc>
         Pseudo-state: first online state (for use in relational expressions).
-        <note internal="yes">
-          For whoever decides to touch this enum: In order to keep the
-          comparisons involving FirstOnline and LastOnline pseudo-states valid,
-          the numeric values of these states must be correspondingly updated if
-          needed: for any online VM state, the condition
-          <tt>FirstOnline &lt;= state &lt;= LastOnline</tt> must be
-          <tt>true</tt>.
-        </note>
       </desc>
     </const>
@@ -580,12 +583,15 @@
       <desc>
         Pseudo-state: last online state (for use in relational expressions).
-        <note internal="yes">
-          For whoever decides to touch this enum: In order to keep the
-          comparisons involving FirstOnline and LastOnline pseudo-states valid,
-          the numeric values of these states must be correspondingly updated if
-          needed: for any online VM state, the condition
-          <tt>FirstOnline &lt;= state &lt;= LastOnline</tt> must be
-          <tt>true</tt>.
-        </note>
+      </desc>
+    </const>
+
+    <const name="FirstTransient" value="7" wsmap="suppress"> <!-- Starting -->
+      <desc>
+        Pseudo-state: first transient state (for use in relational expressions).
+      </desc>
+    </const>
+    <const name="LastTransient"  value="12" wsmap="suppress"> <!-- SettingUp -->
+      <desc>
+        Pseudo-state: last transient state (for use in relational expressions).
       </desc>
     </const>
Index: /trunk/src/VBox/Main/include/Global.h
===================================================================
--- /trunk/src/VBox/Main/include/Global.h	(revision 15761)
+++ /trunk/src/VBox/Main/include/Global.h	(revision 15762)
@@ -66,4 +66,51 @@
 
     static const char *OSTypeId (VBOXOSTYPE aOSType);
+
+    /**
+     * Returns @c true if the given machine state is an online state. This is a
+     * recommended way to detect if the VM is online (being executed in a
+     * dedicated process) or not. Note that some online states are also
+     * transitional states (see #IsTransitional()).
+     */
+    static bool IsOnline (MachineState_T aState)
+    {
+        return aState >= MachineState_FirstOnline &&
+               aState <= MachineState_LastOnline;
+    }
+
+    /**
+     * Returns @c true if the given machine state is a transient state. This is
+     * a recommended way to detect if the VM is performing some potentially
+     * lengthy operation (such as starting, stopping, saving, discarding
+     * snapshot, etc.). Note some (but not all) transitional states are also
+     * online states (see #IsOnline()).
+     */
+    static bool IsTransient (MachineState_T aState)
+    {
+        return aState >= MachineState_FirstTransient &&
+               aState <= MachineState_LastTransient;
+    }
+
+    /**
+     * Shortcut to <tt>IsOnline (aState) || IsTransient (aState)</tt>. When it
+     * returns @false, the VM is turned off (no VM process) and not busy with
+     * another exclusive operation.
+     */
+    static bool IsOnlineOrTransient (MachineState_T aState)
+    {
+        return IsOnline (aState) || IsTransient (aState);
+    }
+
+    /**
+     * Shortcut to <tt>IsOnline (aState) && !IsTransient (aState)</tt>. This is
+     * a recommended way to detect if the VM emulation thread is in action
+     * (either running, suspended, or stuck). When this method returns @false,
+     * then either the VM is not online or the emulation thread is being started
+     * or stopped, etc.
+     */
+    static bool IsActive (MachineState_T aState)
+    {
+        return IsOnline (aState) && !IsTransient (aState);
+    }
 };
 
