Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 51902)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 51903)
@@ -346,4 +346,5 @@
 	src-all/ProgressImpl.cpp \
 	src-all/SharedFolderImpl.cpp \
+	src-all/AutoCaller.cpp \
 	src-all/VirtualBoxBase.cpp \
 	src-all/VirtualBoxErrorInfoImpl.cpp \
@@ -694,4 +695,5 @@
 	src-all/ProgressImpl.cpp \
 	src-all/SharedFolderImpl.cpp \
+	src-all/AutoCaller.cpp \
 	src-all/VirtualBoxBase.cpp \
 	src-all/VirtualBoxErrorInfoImpl.cpp \
@@ -815,4 +817,5 @@
  	src-all/EventImpl.cpp \
  	src-all/Global.cpp \
+	src-all/AutoCaller.cpp \
  	src-all/VirtualBoxBase.cpp \
  	src-all/VirtualBoxErrorInfoImpl.cpp \
Index: /trunk/src/VBox/Main/include/AutoCaller.h
===================================================================
--- /trunk/src/VBox/Main/include/AutoCaller.h	(revision 51902)
+++ /trunk/src/VBox/Main/include/AutoCaller.h	(revision 51903)
@@ -1,9 +1,9 @@
 /** @file
  *
- * VirtualBox COM base classes definition
+ * VirtualBox object caller handling definitions
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -19,4 +19,12 @@
 #define ____H_AUTOCALLER
 
+#include "ObjectState.h"
+
+#include "VBox/com/AutoLock.h"
+
+// Forward declaration needed, but nothing more.
+class VirtualBoxBase;
+
+
 ////////////////////////////////////////////////////////////////////////////////
 //
@@ -25,8 +33,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 
+
 /**
- * Smart class that automatically increases the number of callers of the
- * given VirtualBoxBase object when an instance is constructed and decreases
- * it back when the created instance goes out of scope (i.e. gets destroyed).
+ * Smart class that automatically increases the number of normal (non-limited)
+ * callers of the given VirtualBoxBase object when an instance is constructed
+ * and decreases it back when the created instance goes out of scope (i.e. gets
+ * destroyed).
  *
  * If #rc() returns a failure after the instance creation, it means that
@@ -35,135 +45,6 @@
  * failed result code to the upper level.
  *
- * See VirtualBoxBase::addCaller(), VirtualBoxBase::addLimitedCaller() and
- * VirtualBoxBase::releaseCaller() for more details about object callers.
- *
- * @param aLimited  |false| if this template should use
- *                  VirtualBoxBase::addCaller() calls to add callers, or
- *                  |true| if VirtualBoxBase::addLimitedCaller() should be
- *                  used.
- *
- * @note It is preferable to use the AutoCaller and AutoLimitedCaller
- *       classes than specify the @a aLimited argument, for better
- *       self-descriptiveness.
- */
-template<bool aLimited>
-class AutoCallerBase
-{
-public:
-
-    /**
-     * Increases the number of callers of the given object by calling
-     * VirtualBoxBase::addCaller().
-     *
-     * @param aObj      Object to add a caller to. If NULL, this
-     *                  instance is effectively turned to no-op (where
-     *                  rc() will return S_OK and state() will be
-     *                  NotReady).
-     */
-    AutoCallerBase(VirtualBoxBase *aObj)
-        : mObj(aObj), mRC(S_OK), mState(VirtualBoxBase::NotReady)
-    {
-        if (mObj)
-            mRC = mObj->addCaller(&mState, aLimited);
-    }
-
-    /**
-     * If the number of callers was successfully increased, decreases it
-     * using VirtualBoxBase::releaseCaller(), otherwise does nothing.
-     */
-    ~AutoCallerBase()
-    {
-        if (mObj && SUCCEEDED(mRC))
-            mObj->releaseCaller();
-    }
-
-    /**
-     * Stores the result code returned by VirtualBoxBase::addCaller() after
-     * instance creation or after the last #add() call. A successful result
-     * code means the number of callers was successfully increased.
-     */
-    HRESULT rc() const { return mRC; }
-
-    /**
-     * Returns |true| if |SUCCEEDED(rc())| is |true|, for convenience.
-     * |true| means the number of callers was successfully increased.
-     */
-    bool isOk() const { return SUCCEEDED(mRC); }
-
-    /**
-     * Stores the object state returned by VirtualBoxBase::addCaller() after
-     * instance creation or after the last #add() call.
-     */
-    VirtualBoxBase::State state() const { return mState; }
-
-    /**
-     * Temporarily decreases the number of callers of the managed object.
-     * May only be called if #isOk() returns |true|. Note that #rc() will
-     * return E_FAIL after this method succeeds.
-     */
-    void release()
-    {
-        Assert(SUCCEEDED(mRC));
-        if (SUCCEEDED(mRC))
-        {
-            if (mObj)
-                mObj->releaseCaller();
-            mRC = E_FAIL;
-        }
-    }
-
-    /**
-     * Restores the number of callers decreased by #release(). May only be
-     * called after #release().
-     */
-    void add()
-    {
-        Assert(!SUCCEEDED(mRC));
-        if (mObj && !SUCCEEDED(mRC))
-            mRC = mObj->addCaller(&mState, aLimited);
-    }
-
-    /**
-     * Attaches another object to this caller instance.
-     * The previous object's caller is released before the new one is added.
-     *
-     * @param aObj  New object to attach, may be @c NULL.
-     */
-    void attach(VirtualBoxBase *aObj)
-    {
-        /* detect simple self-reattachment */
-        if (mObj != aObj)
-        {
-            if (mObj && SUCCEEDED(mRC))
-                release();
-            else if (!mObj)
-            {
-                /* Fix up the success state when nothing is attached. Otherwise
-                 * there are a couple of assertion which would trigger. */
-                mRC = E_FAIL;
-            }
-            mObj = aObj;
-            add();
-        }
-    }
-
-    /** Verbose equivalent to <tt>attach (NULL)</tt>. */
-    void detach() { attach(NULL); }
-
-private:
-
-    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoCallerBase)
-    DECLARE_CLS_NEW_DELETE_NOOP(AutoCallerBase)
-
-    VirtualBoxBase *mObj;
-    HRESULT mRC;
-    VirtualBoxBase::State mState;
-};
-
-/**
- * Smart class that automatically increases the number of normal
- * (non-limited) callers of the given VirtualBoxBase object when an instance
- * is constructed and decreases it back when the created instance goes out
- * of scope (i.e. gets destroyed).
+ * See ObjectState::addCaller() and ObjectState::releaseCaller() for more
+ * details about object callers.
  *
  * A typical usage pattern to declare a normal method of some object (i.e. a
@@ -182,12 +63,137 @@
  * }
  * </code>
- *
- * Using this class is equivalent to using the AutoCallerBase template with
- * the @a aLimited argument set to |false|, but this class is preferred
- * because provides better self-descriptiveness.
- *
- * See AutoCallerBase for more information about auto caller functionality.
- */
-typedef AutoCallerBase<false> AutoCaller;
+ */
+class AutoCaller
+{
+public:
+    /**
+     * Default constructor. Not terribly useful, but it's valid to create
+     * an instance without associating it with an object. It's a no-op,
+     * like the more useful constructor below when NULL is passed to it.
+     */
+    AutoCaller()
+    {
+        init(NULL, false);
+    }
+
+    /**
+     * Increases the number of callers of the given object by calling
+     * ObjectState::addCaller() for the corresponding member instance.
+     *
+     * @param aObj      Object to add a normal caller to. If NULL, this
+     *                  instance is effectively turned to no-op (where
+     *                  rc() will return S_OK).
+     */
+    AutoCaller(VirtualBoxBase *aObj)
+    {
+        init(aObj, false);
+    }
+
+    /**
+     * If the number of callers was successfully increased, decreases it
+     * using ObjectState::releaseCaller(), otherwise does nothing.
+     */
+    ~AutoCaller()
+    {
+        if (mObj && SUCCEEDED(mRC))
+            mObj->getObjectState().releaseCaller();
+    }
+
+    /**
+     * Returns the stored result code returned by ObjectState::addCaller()
+     * after instance creation or after the last #add() call. A successful
+     * result code means the number of callers was successfully increased.
+     */
+    HRESULT rc() const { return mRC; }
+
+    /**
+     * Returns |true| if |SUCCEEDED(rc())| is |true|, for convenience.
+     * |true| means the number of callers was successfully increased.
+     */
+    bool isOk() const { return SUCCEEDED(mRC); }
+
+    /**
+     * Temporarily decreases the number of callers of the managed object.
+     * May only be called if #isOk() returns |true|. Note that #rc() will
+     * return E_FAIL after this method succeeds.
+     */
+    void release()
+    {
+        Assert(SUCCEEDED(mRC));
+        if (SUCCEEDED(mRC))
+        {
+            if (mObj)
+                mObj->getObjectState().releaseCaller();
+            mRC = E_FAIL;
+        }
+    }
+
+    /**
+     * Restores the number of callers decreased by #release(). May only be
+     * called after #release().
+     */
+    void add()
+    {
+        Assert(!SUCCEEDED(mRC));
+        if (mObj && !SUCCEEDED(mRC))
+            mRC = mObj->getObjectState().addCaller(mLimited);
+    }
+
+    /**
+     * Attaches another object to this caller instance.
+     * The previous object's caller is released before the new one is added.
+     *
+     * @param aObj  New object to attach, may be @c NULL.
+     */
+    void attach(VirtualBoxBase *aObj)
+    {
+        /* detect simple self-reattachment */
+        if (mObj != aObj)
+        {
+            if (mObj && SUCCEEDED(mRC))
+                release();
+            else if (!mObj)
+            {
+                /* Fix up the success state when nothing is attached. Otherwise
+                 * there are a couple of assertion which would trigger. */
+                mRC = E_FAIL;
+            }
+            mObj = aObj;
+            add();
+        }
+    }
+
+    /** Verbose equivalent to <tt>attach(NULL)</tt>. */
+    void detach() { attach(NULL); }
+
+protected:
+    /**
+     * Internal constructor: Increases the number of callers of the given
+     * object (either normal or limited variant) by calling
+     * ObjectState::addCaller() for the corresponding member instance.
+     *
+     * @param aObj      Object to add a caller to. If NULL, this
+     *                  instance is effectively turned to no-op (where
+     *                  rc() will return S_OK).
+     * @param aLimited  If |false|, then it's a regular caller, otherwise a
+     *                  limited caller.
+     */
+    void init(VirtualBoxBase *aObj, bool aLimited)
+    {
+        mObj = aObj;
+	mRC = S_OK;
+	mLimited = aLimited;
+        if (mObj)
+            mRC = mObj->getObjectState().addCaller(mLimited);
+    }
+
+private:
+    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoCaller)
+    DECLARE_CLS_NEW_DELETE_NOOP(AutoCaller)
+
+    VirtualBoxBase *mObj;
+    HRESULT mRC;
+    bool mLimited;
+};
 
 /**
@@ -212,11 +218,33 @@
  * </code>
  *
- * Using this class is equivalent to using the AutoCallerBase template with
- * the @a aLimited argument set to |true|, but this class is preferred
- * because provides better self-descriptiveness.
- *
- * See AutoCallerBase for more information about auto caller functionality.
- */
-typedef AutoCallerBase<true> AutoLimitedCaller;
+ * See AutoCaller for more information about auto caller functionality.
+ */
+class AutoLimitedCaller : public AutoCaller
+{
+public:
+    /**
+     * Default constructor. Not terribly useful, but it's valid to create
+     * an instance without associating it with an object. It's a no-op,
+     * like the more useful constructor below when NULL is passed to it.
+     */
+    AutoLimitedCaller()
+    {
+        AutoCaller::init(NULL, true);
+    }
+
+    /**
+     * Increases the number of callers of the given object by calling
+     * ObjectState::addCaller() for the corresponding member instance.
+     *
+     * @param aObj      Object to add a limited caller to. If NULL, this
+     *                  instance is effectively turned to no-op (where
+     *                  rc() will return S_OK).
+     */
+    AutoLimitedCaller(VirtualBoxBase *aObj)
+    {
+        AutoCaller::init(aObj, true);
+    }
+
+};
 
 /**
@@ -349,6 +377,6 @@
  * HRESULT Component::reinit()
  * {
- *     AutoReinitSpan autoReinitSpan (this);
- *     AssertReturn (autoReinitSpan.isOk(), E_FAIL);
+ *     AutoReinitSpan autoReinitSpan(this);
+ *     AssertReturn(autoReinitSpan.isOk(), E_FAIL);
  *     ...
  *     if (FAILED(rc))
@@ -416,5 +444,5 @@
  * void Component::uninit()
  * {
- *     AutoUninitSpan autoUninitSpan (this);
+ *     AutoUninitSpan autoUninitSpan(this);
  *     if (autoUninitSpan.uninitDone())
  *         return;
@@ -424,9 +452,9 @@
  *
  * @note The constructor of this class blocks the current thread execution
- *       until the number of callers added to the object using #addCaller()
- *       or AutoCaller drops to zero. For this reason, it is forbidden to
- *       create instances of this class (or call uninit()) within the
- *       AutoCaller or #addCaller() scope because it is a guaranteed
- *       deadlock.
+ *       until the number of callers added to the object using
+ *       ObjectState::addCaller() or AutoCaller drops to zero. For this reason,
+ *       it is forbidden to create instances of this class (or call uninit())
+ *       within the AutoCaller or ObjectState::addCaller() scope because it is
+ *       a guaranteed deadlock.
  *
  * @note Never create instances of this class outside uninit() methods and
Index: /trunk/src/VBox/Main/include/ObjectState.h
===================================================================
--- /trunk/src/VBox/Main/include/ObjectState.h	(revision 51903)
+++ /trunk/src/VBox/Main/include/ObjectState.h	(revision 51903)
@@ -0,0 +1,128 @@
+/** @file
+ *
+ * VirtualBox object state handling definitions
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_OBJECTSTATE
+#define ____H_OBJECTSTATE
+
+#include "VBox/com/defs.h"
+#include "VBox/com/AutoLock.h"
+
+// Forward declaration needed, but nothing more.
+class VirtualBoxBase;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// ObjectState
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Thec functionality implemented by this class is the primary object state
+ * (used by VirtualBoxBase and thus part of all API classes) that indicates
+ * if the object is ready to serve the calls, and if not, what stage it is
+ * currently at. Here is the primary state diagram:
+ *
+ *              +-------------------------------------------------------+
+ *              |                                                       |
+ *              |         (InitFailed) -----------------------+         |
+ *              |              ^                              |         |
+ *              v              |                              v         |
+ *  [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
+ *                     ^       |
+ *                     |       v
+ *                     |    Limited
+ *                     |       |
+ *                     +-------+
+ *
+ * The object is fully operational only when its state is Ready. The Limited
+ * state means that only some vital part of the object is operational, and it
+ * requires some sort of reinitialization to become fully operational. The
+ * NotReady state means the object is basically dead: it either was not yet
+ * initialized after creation at all, or was uninitialized and is waiting to be
+ * destroyed when the last reference to it is released. All other states are
+ * transitional.
+ *
+ * The NotReady->InInit->Ready, NotReady->InInit->Limited and
+ * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
+ * class.
+ *
+ * The Limited->InInit->Ready, Limited->InInit->Limited and
+ * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
+ * class.
+ *
+ * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady
+ * transitions are done by the AutoUninitSpan smart class.
+ *
+ * In order to maintain the primary state integrity and declared functionality
+ * the following rules apply everywhere:
+ *
+ * 1) Use the above Auto*Span classes to perform state transitions. See the
+ *    individual class descriptions for details.
+ *
+ * 2) All public methods of subclasses (i.e. all methods that can be called
+ *    directly, not only from within other methods of the subclass) must have a
+ *    standard prolog as described in the AutoCaller and AutoLimitedCaller
+ *    documentation. Alternatively, they must use #addCaller() and
+ *    #releaseCaller() directly (and therefore have both the prolog and the
+ *    epilog), but this is not recommended because it is easy to forget the
+ *    matching release, e.g. returning before reaching the call.
+ */
+class ObjectState
+{
+public:
+    enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
+
+    ObjectState(VirtualBoxBase *aObj);
+    ~ObjectState();
+
+    State getState();
+
+    HRESULT addCaller(bool aLimited = false);
+    void releaseCaller();
+
+    bool autoInitSpanConstructor(State aExpectedState);
+    void autoInitSpanDestructor(State aNewState);
+    State autoUninitSpanConstructor();
+    void autoUninitSpanDestructor();
+
+private:
+    ObjectState();
+
+    void setState(State aState);
+
+    /** Pointer to the managed object, mostly for error signalling or debugging
+     * purposes, not used much. Guaranteed to be valid during the lifetime of
+     * this object, no need to mess with refcount. */
+    VirtualBoxBase *mObj;
+    /** Primary state of this object */
+    State mState;
+    /** Thread that caused the last state change */
+    RTTHREAD mStateChangeThread;
+    /** Total number of active calls to this object */
+    unsigned mCallers;
+    /** Posted when the number of callers drops to zero */
+    RTSEMEVENT mZeroCallersSem;
+    /** Posted when the object goes from InInit/InUninit to some other state */
+    RTSEMEVENTMULTI mInitUninitSem;
+    /** Number of threads waiting for mInitUninitDoneSem */
+    unsigned mInitUninitWaiters;
+
+    /** Protects access to state related data members */
+    util::RWLockHandle mStateLock;
+};
+
+#endif // !____H_OBJECTSTATE
Index: /trunk/src/VBox/Main/include/VirtualBoxBase.h
===================================================================
--- /trunk/src/VBox/Main/include/VirtualBoxBase.h	(revision 51902)
+++ /trunk/src/VBox/Main/include/VirtualBoxBase.h	(revision 51903)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -24,4 +24,6 @@
 #include <map>
 
+#include "ObjectState.h"
+
 #include "VBox/com/AutoLock.h"
 #include "VBox/com/string.h"
@@ -30,6 +32,5 @@
 #include "VBox/com/VirtualBox.h"
 
-// avoid including VBox/settings.h and VBox/xml.h;
-// only declare the classes
+// avoid including VBox/settings.h and VBox/xml.h; only declare the classes
 namespace xml
 {
@@ -44,7 +45,4 @@
 using namespace com;
 using namespace util;
-
-class AutoInitSpan;
-class AutoUninitSpan;
 
 class VirtualBox;
@@ -665,51 +663,5 @@
  * Declares functionality that should be available in all components.
  *
- * Among the basic functionality implemented by this class is the primary object
- * state that indicates if the object is ready to serve the calls, and if not,
- * what stage it is currently at. Here is the primary state diagram:
- *
- *              +-------------------------------------------------------+
- *              |                                                       |
- *              |         (InitFailed) -----------------------+         |
- *              |              ^                              |         |
- *              v              |                              v         |
- *  [*] ---> NotReady ----> (InInit) -----> Ready -----> (InUninit) ----+
- *                     ^       |
- *                     |       v
- *                     |    Limited
- *                     |       |
- *                     +-------+
- *
- * The object is fully operational only when its state is Ready. The Limited
- * state means that only some vital part of the object is operational, and it
- * requires some sort of reinitialization to become fully operational. The
- * NotReady state means the object is basically dead: it either was not yet
- * initialized after creation at all, or was uninitialized and is waiting to be
- * destroyed when the last reference to it is released. All other states are
- * transitional.
- *
- * The NotReady->InInit->Ready, NotReady->InInit->Limited and
- * NotReady->InInit->InitFailed transition is done by the AutoInitSpan smart
- * class.
- *
- * The Limited->InInit->Ready, Limited->InInit->Limited and
- * Limited->InInit->InitFailed transition is done by the AutoReinitSpan smart
- * class.
- *
- * The Ready->InUninit->NotReady and InitFailed->InUninit->NotReady
- * transitions are done by the AutoUninitSpan smart class.
- *
- * In order to maintain the primary state integrity and declared functionality
- * all subclasses must:
- *
- * 1) Use the above Auto*Span classes to perform state transitions. See the
- *    individual class descriptions for details.
- *
- * 2) All public methods of subclasses (i.e. all methods that can be called
- *    directly, not only from within other methods of the subclass) must have a
- *    standard prolog as described in the AutoCaller and AutoLimitedCaller
- *    documentation. Alternatively, they must use addCaller()/releaseCaller()
- *    directly (and therefore have both the prolog and the epilog), but this is
- *    not recommended.
+ * The object state logic is documented in ObjectState.h.
  */
 class ATL_NO_VTABLE VirtualBoxBase
@@ -744,6 +696,4 @@
 
 public:
-    enum State { NotReady, Ready, InInit, InUninit, InitFailed, Limited };
-
     VirtualBoxBase();
     virtual ~VirtualBoxBase();
@@ -756,22 +706,16 @@
      *
      * @note Never call this method the AutoCaller scope or after the
-     *       #addCaller() call not paired by #releaseCaller() because it is a
-     *       guaranteed deadlock. See AutoUninitSpan for details.
+     *       ObjectState::addCaller() call not paired by
+     *       ObjectState::releaseCaller() because it is a guaranteed deadlock.
+     *       See AutoUninitSpan and AutoCaller.h/ObjectState.h for details.
      */
     virtual void uninit()
     { }
 
-    virtual HRESULT addCaller(State *aState = NULL,
-                              bool aLimited = false);
-    virtual void releaseCaller();
-
-    /**
-     * Adds a limited caller. This method is equivalent to doing
-     * <tt>addCaller(aState, true)</tt>, but it is preferred because provides
-     * better self-descriptiveness. See #addCaller() for more info.
-     */
-    HRESULT addLimitedCaller(State *aState = NULL)
-    {
-        return addCaller(aState, true /* aLimited */);
+    /**
+     */
+    ObjectState &getObjectState()
+    {
+        return mState;
     }
 
@@ -805,12 +749,4 @@
 
     virtual RWLockHandle *lockHandle() const;
-
-    /**
-     * Returns a lock handle used to protect the primary state fields (used by
-     * #addCaller(), AutoInitSpan, AutoUninitSpan, etc.). Only intended to be
-     * used for similar purposes in subclasses. WARNING: NO any other locks may
-     * be requested while holding this lock!
-     */
-    WriteLockHandle *stateLockHandle() { return &mStateLock; }
 
     static HRESULT handleUnexpectedExceptions(VirtualBoxBase *const aThis, RT_SRC_POS_DECL);
@@ -851,34 +787,9 @@
 
 private:
-
-    void setState(State aState)
-    {
-        Assert(mState != aState);
-        mState = aState;
-        mStateChangeThread = RTThreadSelf();
-    }
-
-    /** Primary state of this object */
-    State mState;
-    /** Thread that caused the last state change */
-    RTTHREAD mStateChangeThread;
-    /** Total number of active calls to this object */
-    unsigned mCallers;
-    /** Posted when the number of callers drops to zero */
-    RTSEMEVENT mZeroCallersSem;
-    /** Posted when the object goes from InInit/InUninit to some other state */
-    RTSEMEVENTMULTI mInitUninitSem;
-    /** Number of threads waiting for mInitUninitDoneSem */
-    unsigned mInitUninitWaiters;
-
-    /** Protects access to state related data members */
-    WriteLockHandle mStateLock;
+    /** Object for representing object state */
+    ObjectState mState;
 
     /** User-level object lock for subclasses */
     mutable RWLockHandle *mObjectLock;
-
-    friend class AutoInitSpan;
-    friend class AutoReinitSpan;
-    friend class AutoUninitSpan;
 };
 
Index: /trunk/src/VBox/Main/src-all/AutoCaller.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/AutoCaller.cpp	(revision 51903)
+++ /trunk/src/VBox/Main/src-all/AutoCaller.cpp	(revision 51903)
@@ -0,0 +1,499 @@
+/* $Id$ */
+
+/** @file
+ *
+ * VirtualBox object state implementation
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <iprt/semaphore.h>
+
+#include "VirtualBoxBase.h"
+#include "AutoCaller.h"
+#include "Logging.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// ObjectState methods
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+ObjectState::ObjectState() : mStateLock(LOCKCLASS_OBJECTSTATE)
+{
+    AssertFailed();
+}
+
+ObjectState::ObjectState(VirtualBoxBase *aObj) :
+    mStateLock(LOCKCLASS_OBJECTSTATE), mObj(aObj)
+{
+    Assert(mObj);
+    mState = NotReady;
+    mStateChangeThread = NIL_RTTHREAD;
+    mCallers = 0;
+    mZeroCallersSem = NIL_RTSEMEVENT;
+    mInitUninitSem = NIL_RTSEMEVENTMULTI;
+    mInitUninitWaiters = 0;
+}
+
+ObjectState::~ObjectState()
+{
+    Assert(mInitUninitWaiters == 0);
+    Assert(mInitUninitSem == NIL_RTSEMEVENTMULTI);
+    if (mZeroCallersSem != NIL_RTSEMEVENT)
+        RTSemEventDestroy(mZeroCallersSem);
+    mCallers = 0;
+    mStateChangeThread = NIL_RTTHREAD;
+    mState = NotReady;
+    mObj = NULL;
+}
+
+ObjectState::State ObjectState::getState()
+{
+    AutoReadLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+    return mState;
+}
+
+/**
+ * Increments the number of calls to this object by one.
+ *
+ * After this method succeeds, it is guaranteed that the object will remain
+ * in the Ready (or in the Limited) state at least until #releaseCaller() is
+ * called.
+ *
+ * This method is intended to mark the beginning of sections of code within
+ * methods of COM objects that depend on the readiness (Ready) state. The
+ * Ready state is a primary "ready to serve" state. Usually all code that
+ * works with component's data depends on it. On practice, this means that
+ * almost every public method, setter or getter of the object should add
+ * itself as an object's caller at the very beginning, to protect from an
+ * unexpected uninitialization that may happen on a different thread.
+ *
+ * Besides the Ready state denoting that the object is fully functional,
+ * there is a special Limited state. The Limited state means that the object
+ * is still functional, but its functionality is limited to some degree, so
+ * not all operations are possible. The @a aLimited argument to this method
+ * determines whether the caller represents this limited functionality or
+ * not.
+ *
+ * This method succeeds (and increments the number of callers) only if the
+ * current object's state is Ready. Otherwise, it will return E_ACCESSDENIED
+ * to indicate that the object is not operational. There are two exceptions
+ * from this rule:
+ * <ol>
+ *   <li>If the @a aLimited argument is |true|, then this method will also
+ *       succeed if the object's state is Limited (or Ready, of course).
+ *   </li>
+ *   <li>If this method is called from the same thread that placed
+ *       the object to InInit or InUninit state (i.e. either from within the
+ *       AutoInitSpan or AutoUninitSpan scope), it will succeed as well (but
+ *       will not increase the number of callers).
+ *   </li>
+ * </ol>
+ *
+ * Normally, calling addCaller() never blocks. However, if this method is
+ * called by a thread created from within the AutoInitSpan scope and this
+ * scope is still active (i.e. the object state is InInit), it will block
+ * until the AutoInitSpan destructor signals that it has finished
+ * initialization.
+ *
+ * When this method returns a failure, the caller must not use the object
+ * and should return the failed result code to its own caller.
+ *
+ * @param aLimited      |true| to add a limited caller.
+ *
+ * @return              S_OK on success or E_ACCESSDENIED on failure.
+ *
+ * @sa #releaseCaller()
+ */
+HRESULT ObjectState::addCaller(bool aLimited /* = false */)
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    HRESULT rc = E_ACCESSDENIED;
+
+    if (mState == Ready || (aLimited && mState == Limited))
+    {
+        /* if Ready or allows Limited, increase the number of callers */
+        ++mCallers;
+        rc = S_OK;
+    }
+    else
+    if (mState == InInit || mState == InUninit)
+    {
+        if (mStateChangeThread == RTThreadSelf())
+        {
+            /* Called from the same thread that is doing AutoInitSpan or
+             * AutoUninitSpan, just succeed */
+            rc = S_OK;
+        }
+        else if (mState == InInit)
+        {
+            /* addCaller() is called by a "child" thread while the "parent"
+             * thread is still doing AutoInitSpan/AutoReinitSpan, so wait for
+             * the state to become either Ready/Limited or InitFailed (in
+             * case of init failure).
+             *
+             * Note that we increase the number of callers anyway -- to
+             * prevent AutoUninitSpan from early completion if we are
+             * still not scheduled to pick up the posted semaphore when
+             * uninit() is called.
+             */
+            ++mCallers;
+
+            /* lazy semaphore creation */
+            if (mInitUninitSem == NIL_RTSEMEVENTMULTI)
+            {
+                RTSemEventMultiCreate(&mInitUninitSem);
+                Assert(mInitUninitWaiters == 0);
+            }
+
+            ++mInitUninitWaiters;
+
+            LogFlowThisFunc(("Waiting for AutoInitSpan/AutoReinitSpan to finish...\n"));
+
+            stateLock.release();
+            RTSemEventMultiWait(mInitUninitSem, RT_INDEFINITE_WAIT);
+            stateLock.acquire();
+
+            if (--mInitUninitWaiters == 0)
+            {
+                /* destroy the semaphore since no more necessary */
+                RTSemEventMultiDestroy(mInitUninitSem);
+                mInitUninitSem = NIL_RTSEMEVENTMULTI;
+            }
+
+            if (mState == Ready || (aLimited && mState == Limited))
+                rc = S_OK;
+            else
+            {
+                Assert(mCallers != 0);
+                --mCallers;
+                if (mCallers == 0 && mState == InUninit)
+                {
+                    /* inform AutoUninitSpan ctor there are no more callers */
+                    RTSemEventSignal(mZeroCallersSem);
+                }
+            }
+        }
+    }
+
+    if (FAILED(rc))
+    {
+        if (mState == Limited)
+            rc = mObj->setError(rc, "The object functionality is limited");
+        else
+            rc = mObj->setError(rc, "The object is not ready");
+    }
+
+    return rc;
+}
+
+/**
+ * Decreases the number of calls to this object by one.
+ *
+ * Must be called after every #addCaller() when protecting the object
+ * from uninitialization is no more necessary.
+ */
+void ObjectState::releaseCaller()
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    if (mState == Ready || mState == Limited)
+    {
+        /* if Ready or Limited, decrease the number of callers */
+        AssertMsgReturn(mCallers != 0, ("mCallers is ZERO!"), (void) 0);
+        --mCallers;
+
+        return;
+    }
+
+    if (mState == InInit || mState == InUninit)
+    {
+        if (mStateChangeThread == RTThreadSelf())
+        {
+            /* Called from the same thread that is doing AutoInitSpan or
+             * AutoUninitSpan: just succeed */
+            return;
+        }
+
+        if (mState == InUninit)
+        {
+            /* the caller is being released after AutoUninitSpan has begun */
+            AssertMsgReturn(mCallers != 0, ("mCallers is ZERO!"), (void) 0);
+            --mCallers;
+
+            if (mCallers == 0)
+                /* inform the Auto*UninitSpan ctor there are no more callers */
+                RTSemEventSignal(mZeroCallersSem);
+
+            return;
+        }
+    }
+
+    AssertMsgFailed(("mState = %d!", mState));
+}
+
+bool ObjectState::autoInitSpanConstructor(ObjectState::State aExpectedState)
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    if (mState == aExpectedState)
+    {
+        setState(InInit);
+        return true;
+    }
+    else
+        return false;
+}
+
+void ObjectState::autoInitSpanDestructor(State aNewState)
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    Assert(mState == InInit);
+
+    if (mCallers > 0 && mInitUninitWaiters > 0)
+    {
+        /* We have some pending addCaller() calls on other threads (created
+         * during InInit), signal that InInit is finished and they may go on. */
+        RTSemEventMultiSignal(mInitUninitSem);
+    }
+
+    setState(aNewState);
+}
+
+ObjectState::State ObjectState::autoUninitSpanConstructor()
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    Assert(mState != InInit);
+
+    if (mState == NotReady)
+    {
+        /* do nothing if already uninitialized */
+        return mState;
+    }
+    else if (mState == InUninit)
+    {
+        /* Another thread has already started uninitialization, wait for its
+         * completion. This is necessary to make sure that when this method
+         * returns, the object state is well-defined (NotReady). */
+
+        /* lazy semaphore creation */
+        if (mInitUninitSem == NIL_RTSEMEVENTMULTI)
+        {
+            RTSemEventMultiCreate(&mInitUninitSem);
+            Assert(mInitUninitWaiters == 0);
+        }
+        ++mInitUninitWaiters;
+
+        LogFlowFunc(("{%p}: Waiting for AutoUninitSpan to finish...\n", mObj));
+
+        stateLock.release();
+        RTSemEventMultiWait(mInitUninitSem, RT_INDEFINITE_WAIT);
+        stateLock.acquire();
+
+        if (--mInitUninitWaiters == 0)
+        {
+            /* destroy the semaphore since no more necessary */
+            RTSemEventMultiDestroy(mInitUninitSem);
+            mInitUninitSem = NIL_RTSEMEVENTMULTI;
+        }
+
+        /* the other thread set it to NotReady */
+        return mState;
+    }
+
+    /* go to InUninit to prevent from adding new callers */
+    setState(InUninit);
+
+    /* wait for already existing callers to drop to zero */
+    if (mCallers > 0)
+    {
+        /* lazy creation */
+        Assert(mZeroCallersSem == NIL_RTSEMEVENT);
+        RTSemEventCreate(&mZeroCallersSem);
+
+        /* wait until remaining callers release the object */
+        LogFlowFunc(("{%p}: Waiting for callers (%d) to drop to zero...\n",
+                     mObj, mCallers));
+
+        stateLock.release();
+        RTSemEventWait(mZeroCallersSem, RT_INDEFINITE_WAIT);
+    }
+    return mState;
+}
+
+void ObjectState::autoUninitSpanDestructor()
+{
+    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
+
+    Assert(mState == InUninit);
+
+    setState(NotReady);
+}
+
+
+void ObjectState::setState(ObjectState::State aState)
+{
+    Assert(mState != aState);
+    mState = aState;
+    mStateChangeThread = RTThreadSelf();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoInitSpan methods
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Creates a smart initialization span object that places the object to
+ * InInit state.
+ *
+ * Please see the AutoInitSpan class description for more info.
+ *
+ * @param aObj      |this| pointer of the managed VirtualBoxBase object whose
+ *                  init() method is being called.
+ * @param aResult   Default initialization result.
+ */
+AutoInitSpan::AutoInitSpan(VirtualBoxBase *aObj,
+                           Result aResult /* = Failed */)
+    : mObj(aObj),
+      mResult(aResult),
+      mOk(false)
+{
+    Assert(mObj);
+    mOk = mObj->getObjectState().autoInitSpanConstructor(ObjectState::NotReady);
+    AssertReturnVoid(mOk);
+}
+
+/**
+ * Places the managed VirtualBoxBase object to Ready/Limited state if the
+ * initialization succeeded or partly succeeded, or places it to InitFailed
+ * state and calls the object's uninit() method.
+ *
+ * Please see the AutoInitSpan class description for more info.
+ */
+AutoInitSpan::~AutoInitSpan()
+{
+    /* if the state was other than NotReady, do nothing */
+    if (!mOk)
+        return;
+
+    ObjectState::State newState;
+    if (mResult == Succeeded)
+        newState = ObjectState::Ready;
+    else if (mResult == Limited)
+        newState = ObjectState::Limited;
+    else
+        newState = ObjectState::InitFailed;
+    mObj->getObjectState().autoInitSpanDestructor(newState);
+    if (newState == ObjectState::InitFailed)
+    {
+        /* call uninit() to let the object uninit itself after failed init() */
+        mObj->uninit();
+        /* Note: the object may no longer exist here (for example, it can call
+         * the destructor in uninit()) */
+    }
+}
+
+// AutoReinitSpan methods
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Creates a smart re-initialization span object and places the object to
+ * InInit state.
+ *
+ * Please see the AutoInitSpan class description for more info.
+ *
+ * @param aObj      |this| pointer of the managed VirtualBoxBase object whose
+ *                  re-initialization method is being called.
+ */
+AutoReinitSpan::AutoReinitSpan(VirtualBoxBase *aObj)
+    : mObj(aObj),
+      mSucceeded(false),
+      mOk(false)
+{
+    Assert(mObj);
+    mOk = mObj->getObjectState().autoInitSpanConstructor(ObjectState::Limited);
+    AssertReturnVoid(mOk);
+}
+
+/**
+ * Places the managed VirtualBoxBase object to Ready state if the
+ * re-initialization succeeded (i.e. #setSucceeded() has been called) or back to
+ * Limited state otherwise.
+ *
+ * Please see the AutoInitSpan class description for more info.
+ */
+AutoReinitSpan::~AutoReinitSpan()
+{
+    /* if the state was other than Limited, do nothing */
+    if (!mOk)
+        return;
+
+    ObjectState::State newState;
+    if (mSucceeded)
+        newState = ObjectState::Ready;
+    else
+        newState = ObjectState::Limited;
+    mObj->getObjectState().autoInitSpanDestructor(newState);
+    /** @todo r=klaus: this is like the initial init() failure, but in this
+     * place uninit() is NOT called. Makes only limited sense. */
+}
+
+// AutoUninitSpan methods
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Creates a smart uninitialization span object and places this object to
+ * InUninit state.
+ *
+ * Please see the AutoInitSpan class description for more info.
+ *
+ * @note This method blocks the current thread execution until the number of
+ *       callers of the managed VirtualBoxBase object drops to zero!
+ *
+ * @param aObj  |this| pointer of the VirtualBoxBase object whose uninit()
+ *              method is being called.
+ */
+AutoUninitSpan::AutoUninitSpan(VirtualBoxBase *aObj)
+    : mObj(aObj),
+      mInitFailed(false),
+      mUninitDone(false)
+{
+    Assert(mObj);
+    ObjectState::State state;
+    state = mObj->getObjectState().autoUninitSpanConstructor();
+    if (state == ObjectState::InitFailed)
+        mInitFailed = true;
+    else if (state == ObjectState::NotReady)
+        mUninitDone = true;
+}
+
+/**
+ *  Places the managed VirtualBoxBase object to the NotReady state.
+ */
+AutoUninitSpan::~AutoUninitSpan()
+{
+    /* do nothing if already uninitialized */
+    if (mUninitDone)
+        return;
+
+    mObj->getObjectState().autoUninitSpanDestructor();
+}
Index: /trunk/src/VBox/Main/src-all/VirtualBoxBase.cpp
===================================================================
--- /trunk/src/VBox/Main/src-all/VirtualBoxBase.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-all/VirtualBoxBase.cpp	(revision 51903)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -24,12 +24,12 @@
 #include <typeinfo>
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 #include <windows.h>
 #include <dbghelp.h>
-#else /* !defined (VBOX_WITH_XPCOM) */
+#else /* !defined(VBOX_WITH_XPCOM) */
 /// @todo remove when VirtualBoxErrorInfo goes away from here
 #include <nsIServiceManager.h>
 #include <nsIExceptionService.h>
-#endif /* !defined (VBOX_WITH_XPCOM) */
+#endif /* !defined(VBOX_WITH_XPCOM) */
 
 #include "VirtualBoxBase.h"
@@ -47,13 +47,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 
-VirtualBoxBase::VirtualBoxBase()
-    : mStateLock(LOCKCLASS_OBJECTSTATE)
-{
-    mState = NotReady;
-    mStateChangeThread = NIL_RTTHREAD;
-    mCallers = 0;
-    mZeroCallersSem = NIL_RTSEMEVENT;
-    mInitUninitSem = NIL_RTSEMEVENTMULTI;
-    mInitUninitWaiters = 0;
+VirtualBoxBase::VirtualBoxBase() : mState(this)
+{
     mObjectLock = NULL;
 }
@@ -63,11 +56,4 @@
     if (mObjectLock)
         delete mObjectLock;
-    Assert(mInitUninitWaiters == 0);
-    Assert(mInitUninitSem == NIL_RTSEMEVENTMULTI);
-    if (mZeroCallersSem != NIL_RTSEMEVENT)
-        RTSemEventDestroy (mZeroCallersSem);
-    mCallers = 0;
-    mStateChangeThread = NIL_RTTHREAD;
-    mState = NotReady;
 }
 
@@ -90,5 +76,5 @@
     if (RT_UNLIKELY(!mObjectLock))
     {
-        AssertCompile (sizeof (RWLockHandle *) == sizeof (void *));
+        AssertCompile(sizeof(RWLockHandle *) == sizeof(void *));
 
         // getLockingClass() is overridden by many subclasses to return
@@ -103,196 +89,4 @@
     }
     return mObjectLock;
-}
-
-/**
- * Increments the number of calls to this object by one.
- *
- * After this method succeeds, it is guaranteed that the object will remain
- * in the Ready (or in the Limited) state at least until #releaseCaller() is
- * called.
- *
- * This method is intended to mark the beginning of sections of code within
- * methods of COM objects that depend on the readiness (Ready) state. The
- * Ready state is a primary "ready to serve" state. Usually all code that
- * works with component's data depends on it. On practice, this means that
- * almost every public method, setter or getter of the object should add
- * itself as an object's caller at the very beginning, to protect from an
- * unexpected uninitialization that may happen on a different thread.
- *
- * Besides the Ready state denoting that the object is fully functional,
- * there is a special Limited state. The Limited state means that the object
- * is still functional, but its functionality is limited to some degree, so
- * not all operations are possible. The @a aLimited argument to this method
- * determines whether the caller represents this limited functionality or
- * not.
- *
- * This method succeeds (and increments the number of callers) only if the
- * current object's state is Ready. Otherwise, it will return E_ACCESSDENIED
- * to indicate that the object is not operational. There are two exceptions
- * from this rule:
- * <ol>
- *   <li>If the @a aLimited argument is |true|, then this method will also
- *       succeed if the object's state is Limited (or Ready, of course).
- *   </li>
- *   <li>If this method is called from the same thread that placed
- *       the object to InInit or InUninit state (i.e. either from within the
- *       AutoInitSpan or AutoUninitSpan scope), it will succeed as well (but
- *       will not increase the number of callers).
- *   </li>
- * </ol>
- *
- * Normally, calling addCaller() never blocks. However, if this method is
- * called by a thread created from within the AutoInitSpan scope and this
- * scope is still active (i.e. the object state is InInit), it will block
- * until the AutoInitSpan destructor signals that it has finished
- * initialization.
- *
- * When this method returns a failure, the caller must not use the object
- * and should return the failed result code to its own caller.
- *
- * @param aState        Where to store the current object's state (can be
- *                      used in overridden methods to determine the cause of
- *                      the failure).
- * @param aLimited      |true| to add a limited caller.
- *
- * @return              S_OK on success or E_ACCESSDENIED on failure.
- *
- * @note It is preferable to use the #addLimitedCaller() rather than
- *       calling this method with @a aLimited = |true|, for better
- *       self-descriptiveness.
- *
- * @sa #addLimitedCaller()
- * @sa #releaseCaller()
- */
-HRESULT VirtualBoxBase::addCaller(State *aState /* = NULL */,
-                                  bool aLimited /* = false */)
-{
-    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    HRESULT rc = E_ACCESSDENIED;
-
-    if (mState == Ready || (aLimited && mState == Limited))
-    {
-        /* if Ready or allows Limited, increase the number of callers */
-        ++ mCallers;
-        rc = S_OK;
-    }
-    else
-    if (mState == InInit || mState == InUninit)
-    {
-        if (mStateChangeThread == RTThreadSelf())
-        {
-            /* Called from the same thread that is doing AutoInitSpan or
-             * AutoUninitSpan, just succeed */
-            rc = S_OK;
-        }
-        else if (mState == InInit)
-        {
-            /* addCaller() is called by a "child" thread while the "parent"
-             * thread is still doing AutoInitSpan/AutoReinitSpan, so wait for
-             * the state to become either Ready/Limited or InitFailed (in
-             * case of init failure).
-             *
-             * Note that we increase the number of callers anyway -- to
-             * prevent AutoUninitSpan from early completion if we are
-             * still not scheduled to pick up the posted semaphore when
-             * uninit() is called.
-             */
-            ++ mCallers;
-
-            /* lazy semaphore creation */
-            if (mInitUninitSem == NIL_RTSEMEVENTMULTI)
-            {
-                RTSemEventMultiCreate (&mInitUninitSem);
-                Assert(mInitUninitWaiters == 0);
-            }
-
-            ++ mInitUninitWaiters;
-
-            LogFlowThisFunc(("Waiting for AutoInitSpan/AutoReinitSpan to finish...\n"));
-
-            stateLock.release();
-            RTSemEventMultiWait (mInitUninitSem, RT_INDEFINITE_WAIT);
-            stateLock.acquire();
-
-            if (-- mInitUninitWaiters == 0)
-            {
-                /* destroy the semaphore since no more necessary */
-                RTSemEventMultiDestroy (mInitUninitSem);
-                mInitUninitSem = NIL_RTSEMEVENTMULTI;
-            }
-
-            if (mState == Ready || (aLimited && mState == Limited))
-                rc = S_OK;
-            else
-            {
-                Assert(mCallers != 0);
-                -- mCallers;
-                if (mCallers == 0 && mState == InUninit)
-                {
-                    /* inform AutoUninitSpan ctor there are no more callers */
-                    RTSemEventSignal(mZeroCallersSem);
-                }
-            }
-        }
-    }
-
-    if (aState)
-        *aState = mState;
-
-    if (FAILED(rc))
-    {
-        if (mState == VirtualBoxBase::Limited)
-            rc = setError(rc, "The object functionality is limited");
-        else
-            rc = setError(rc, "The object is not ready");
-    }
-
-    return rc;
-}
-
-/**
- * Decreases the number of calls to this object by one.
- *
- * Must be called after every #addCaller() or #addLimitedCaller() when
- * protecting the object from uninitialization is no more necessary.
- */
-void VirtualBoxBase::releaseCaller()
-{
-    AutoWriteLock stateLock(mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    if (mState == Ready || mState == Limited)
-    {
-        /* if Ready or Limited, decrease the number of callers */
-        AssertMsgReturn(mCallers != 0, ("mCallers is ZERO!"), (void) 0);
-        --mCallers;
-
-        return;
-    }
-
-    if (mState == InInit || mState == InUninit)
-    {
-        if (mStateChangeThread == RTThreadSelf())
-        {
-            /* Called from the same thread that is doing AutoInitSpan or
-             * AutoUninitSpan: just succeed */
-            return;
-        }
-
-        if (mState == InUninit)
-        {
-            /* the caller is being released after AutoUninitSpan has begun */
-            AssertMsgReturn(mCallers != 0, ("mCallers is ZERO!"), (void) 0);
-            --mCallers;
-
-            if (mCallers == 0)
-                /* inform the Auto*UninitSpan ctor there are no more callers */
-                RTSemEventSignal(mZeroCallersSem);
-
-            return;
-        }
-    }
-
-    AssertMsgFailed (("mState = %d!", mState));
 }
 
@@ -437,5 +231,5 @@
         if (FAILED(rc)) break;
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 
         ComPtr<IVirtualBoxErrorInfo> curInfo;
@@ -444,5 +238,5 @@
             /* get the current error info if any */
             ComPtr<IErrorInfo> err;
-            rc = ::GetErrorInfo (0, err.asOutParam());
+            rc = ::GetErrorInfo(0, err.asOutParam());
             if (FAILED(rc)) break;
             rc = err.queryInterfaceTo(curInfo.asOutParam());
@@ -455,5 +249,5 @@
                 if (SUCCEEDED(rc))
                 {
-                    rc = wrapper->init (err);
+                    rc = wrapper->init(err);
                     if (SUCCEEDED(rc))
                         curInfo = wrapper;
@@ -471,14 +265,14 @@
         rc = info.queryInterfaceTo(err.asOutParam());
         if (SUCCEEDED(rc))
-            rc = ::SetErrorInfo (0, err);
-
-#else // !defined (VBOX_WITH_XPCOM)
+            rc = ::SetErrorInfo(0, err);
+
+#else // !defined(VBOX_WITH_XPCOM)
 
         nsCOMPtr <nsIExceptionService> es;
-        es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+        es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
         if (NS_SUCCEEDED(rc))
         {
             nsCOMPtr <nsIExceptionManager> em;
-            rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+            rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
             if (FAILED(rc)) break;
 
@@ -488,5 +282,5 @@
                 /* get the current error info if any */
                 ComPtr<nsIException> ex;
-                rc = em->GetCurrentException (ex.asOutParam());
+                rc = em->GetCurrentException(ex.asOutParam());
                 if (FAILED(rc)) break;
                 rc = ex.queryInterfaceTo(curInfo.asOutParam());
@@ -499,5 +293,5 @@
                     if (SUCCEEDED(rc))
                     {
-                        rc = wrapper->init (ex);
+                        rc = wrapper->init(ex);
                         if (SUCCEEDED(rc))
                             curInfo = wrapper;
@@ -515,5 +309,5 @@
             rc = info.queryInterfaceTo(ex.asOutParam());
             if (SUCCEEDED(rc))
-                rc = em->SetCurrentException (ex);
+                rc = em->SetCurrentException(ex);
         }
         else if (rc == NS_ERROR_UNEXPECTED)
@@ -533,9 +327,9 @@
         }
 
-#endif // !defined (VBOX_WITH_XPCOM)
+#endif // !defined(VBOX_WITH_XPCOM)
     }
     while (0);
 
-    AssertComRC (rc);
+    AssertComRC(rc);
 
     return SUCCEEDED(rc) ? aResultCode : rc;
@@ -604,5 +398,5 @@
         if (FAILED(rc)) break;
 
-#if !defined (VBOX_WITH_XPCOM)
+#if !defined(VBOX_WITH_XPCOM)
 
         ComPtr<IVirtualBoxErrorInfo> curInfo;
@@ -611,5 +405,5 @@
             /* get the current error info if any */
             ComPtr<IErrorInfo> err;
-            rc = ::GetErrorInfo (0, err.asOutParam());
+            rc = ::GetErrorInfo(0, err.asOutParam());
             if (FAILED(rc)) break;
             rc = err.queryInterfaceTo(curInfo.asOutParam());
@@ -622,5 +416,5 @@
                 if (SUCCEEDED(rc))
                 {
-                    rc = wrapper->init (err);
+                    rc = wrapper->init(err);
                     if (SUCCEEDED(rc))
                         curInfo = wrapper;
@@ -638,14 +432,14 @@
         rc = info.queryInterfaceTo(err.asOutParam());
         if (SUCCEEDED(rc))
-            rc = ::SetErrorInfo (0, err);
-
-#else // !defined (VBOX_WITH_XPCOM)
+            rc = ::SetErrorInfo(0, err);
+
+#else // !defined(VBOX_WITH_XPCOM)
 
         nsCOMPtr <nsIExceptionService> es;
-        es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
+        es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rc);
         if (NS_SUCCEEDED(rc))
         {
             nsCOMPtr <nsIExceptionManager> em;
-            rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+            rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
             if (FAILED(rc)) break;
 
@@ -655,5 +449,5 @@
                 /* get the current error info if any */
                 ComPtr<nsIException> ex;
-                rc = em->GetCurrentException (ex.asOutParam());
+                rc = em->GetCurrentException(ex.asOutParam());
                 if (FAILED(rc)) break;
                 rc = ex.queryInterfaceTo(curInfo.asOutParam());
@@ -666,5 +460,5 @@
                     if (SUCCEEDED(rc))
                     {
-                        rc = wrapper->init (ex);
+                        rc = wrapper->init(ex);
                         if (SUCCEEDED(rc))
                             curInfo = wrapper;
@@ -682,5 +476,5 @@
             rc = info.queryInterfaceTo(ex.asOutParam());
             if (SUCCEEDED(rc))
-                rc = em->SetCurrentException (ex);
+                rc = em->SetCurrentException(ex);
         }
         else if (rc == NS_ERROR_UNEXPECTED)
@@ -700,9 +494,9 @@
         }
 
-#endif // !defined (VBOX_WITH_XPCOM)
+#endif // !defined(VBOX_WITH_XPCOM)
     }
     while (0);
 
-    AssertComRC (rc);
+    AssertComRC(rc);
 
     return SUCCEEDED(rc) ? ei.getResultCode() : rc;
@@ -756,5 +550,5 @@
 {
 #if !defined(VBOX_WITH_XPCOM)
-    ::SetErrorInfo (0, NULL);
+    ::SetErrorInfo(0, NULL);
 #else
     HRESULT rc = S_OK;
@@ -764,5 +558,5 @@
     {
         nsCOMPtr <nsIExceptionManager> em;
-        rc = es->GetCurrentExceptionManager (getter_AddRefs (em));
+        rc = es->GetCurrentExceptionManager(getter_AddRefs(em));
         if (SUCCEEDED(rc))
             em->SetCurrentException(NULL);
@@ -771,254 +565,4 @@
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// AutoInitSpan methods
-//
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Creates a smart initialization span object that places the object to
- * InInit state.
- *
- * Please see the AutoInitSpan class description for more info.
- *
- * @param aObj      |this| pointer of the managed VirtualBoxBase object whose
- *                  init() method is being called.
- * @param aResult   Default initialization result.
- */
-AutoInitSpan::AutoInitSpan(VirtualBoxBase *aObj,
-                           Result aResult /* = Failed */)
-    : mObj(aObj),
-      mResult(aResult),
-      mOk(false)
-{
-    Assert(aObj);
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    mOk = mObj->mState == VirtualBoxBase::NotReady;
-    AssertReturnVoid (mOk);
-
-    mObj->setState(VirtualBoxBase::InInit);
-}
-
-/**
- * Places the managed VirtualBoxBase object to Ready/Limited state if the
- * initialization succeeded or partly succeeded, or places it to InitFailed
- * state and calls the object's uninit() method.
- *
- * Please see the AutoInitSpan class description for more info.
- */
-AutoInitSpan::~AutoInitSpan()
-{
-    /* if the state was other than NotReady, do nothing */
-    if (!mOk)
-        return;
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    Assert(mObj->mState == VirtualBoxBase::InInit);
-
-    if (mObj->mCallers > 0)
-    {
-        Assert(mObj->mInitUninitWaiters > 0);
-
-        /* We have some pending addCaller() calls on other threads (created
-         * during InInit), signal that InInit is finished and they may go on. */
-        RTSemEventMultiSignal(mObj->mInitUninitSem);
-    }
-
-    if (mResult == Succeeded)
-    {
-        mObj->setState(VirtualBoxBase::Ready);
-    }
-    else
-    if (mResult == Limited)
-    {
-        mObj->setState(VirtualBoxBase::Limited);
-    }
-    else
-    {
-        mObj->setState(VirtualBoxBase::InitFailed);
-        /* release the lock to prevent nesting when uninit() is called */
-        stateLock.release();
-        /* call uninit() to let the object uninit itself after failed init() */
-        mObj->uninit();
-        /* Note: the object may no longer exist here (for example, it can call
-         * the destructor in uninit()) */
-    }
-}
-
-// AutoReinitSpan methods
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Creates a smart re-initialization span object and places the object to
- * InInit state.
- *
- * Please see the AutoInitSpan class description for more info.
- *
- * @param aObj      |this| pointer of the managed VirtualBoxBase object whose
- *                  re-initialization method is being called.
- */
-AutoReinitSpan::AutoReinitSpan(VirtualBoxBase *aObj)
-    : mObj(aObj),
-      mSucceeded(false),
-      mOk(false)
-{
-    Assert(aObj);
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    mOk = mObj->mState == VirtualBoxBase::Limited;
-    AssertReturnVoid (mOk);
-
-    mObj->setState(VirtualBoxBase::InInit);
-}
-
-/**
- * Places the managed VirtualBoxBase object to Ready state if the
- * re-initialization succeeded (i.e. #setSucceeded() has been called) or back to
- * Limited state otherwise.
- *
- * Please see the AutoInitSpan class description for more info.
- */
-AutoReinitSpan::~AutoReinitSpan()
-{
-    /* if the state was other than Limited, do nothing */
-    if (!mOk)
-        return;
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    Assert(mObj->mState == VirtualBoxBase::InInit);
-
-    if (mObj->mCallers > 0 && mObj->mInitUninitWaiters > 0)
-    {
-        /* We have some pending addCaller() calls on other threads (created
-         * during InInit), signal that InInit is finished and they may go on. */
-        RTSemEventMultiSignal(mObj->mInitUninitSem);
-    }
-
-    if (mSucceeded)
-    {
-        mObj->setState(VirtualBoxBase::Ready);
-    }
-    else
-    {
-        mObj->setState(VirtualBoxBase::Limited);
-    }
-}
-
-// AutoUninitSpan methods
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Creates a smart uninitialization span object and places this object to
- * InUninit state.
- *
- * Please see the AutoInitSpan class description for more info.
- *
- * @note This method blocks the current thread execution until the number of
- *       callers of the managed VirtualBoxBase object drops to zero!
- *
- * @param aObj  |this| pointer of the VirtualBoxBase object whose uninit()
- *              method is being called.
- */
-AutoUninitSpan::AutoUninitSpan(VirtualBoxBase *aObj)
-    : mObj(aObj),
-      mInitFailed(false),
-      mUninitDone(false)
-{
-    Assert(aObj);
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    Assert(mObj->mState != VirtualBoxBase::InInit);
-
-    /* Set mUninitDone to |true| if this object is already uninitialized
-     * (NotReady) or if another AutoUninitSpan is currently active on some
-     *  other thread (InUninit). */
-    mUninitDone =    mObj->mState == VirtualBoxBase::NotReady
-                  || mObj->mState == VirtualBoxBase::InUninit;
-
-    if (mObj->mState == VirtualBoxBase::InitFailed)
-    {
-        /* we've been called by init() on failure */
-        mInitFailed = true;
-    }
-    else
-    {
-        if (mUninitDone)
-        {
-            /* do nothing if already uninitialized */
-            if (mObj->mState == VirtualBoxBase::NotReady)
-                return;
-
-            /* otherwise, wait until another thread finishes uninitialization.
-             * This is necessary to make sure that when this method returns, the
-             * object is NotReady and therefore can be deleted (for example). */
-
-            /* lazy semaphore creation */
-            if (mObj->mInitUninitSem == NIL_RTSEMEVENTMULTI)
-            {
-                RTSemEventMultiCreate(&mObj->mInitUninitSem);
-                Assert(mObj->mInitUninitWaiters == 0);
-            }
-            ++mObj->mInitUninitWaiters;
-
-            LogFlowFunc(("{%p}: Waiting for AutoUninitSpan to finish...\n",
-                         mObj));
-
-            stateLock.release();
-            RTSemEventMultiWait(mObj->mInitUninitSem, RT_INDEFINITE_WAIT);
-            stateLock.acquire();
-
-            if (--mObj->mInitUninitWaiters == 0)
-            {
-                /* destroy the semaphore since no more necessary */
-                RTSemEventMultiDestroy(mObj->mInitUninitSem);
-                mObj->mInitUninitSem = NIL_RTSEMEVENTMULTI;
-            }
-
-            return;
-        }
-    }
-
-    /* go to InUninit to prevent from adding new callers */
-    mObj->setState(VirtualBoxBase::InUninit);
-
-    /* wait for already existing callers to drop to zero */
-    if (mObj->mCallers > 0)
-    {
-        /* lazy creation */
-        Assert(mObj->mZeroCallersSem == NIL_RTSEMEVENT);
-        RTSemEventCreate(&mObj->mZeroCallersSem);
-
-        /* wait until remaining callers release the object */
-        LogFlowFunc(("{%p}: Waiting for callers (%d) to drop to zero...\n",
-                     mObj, mObj->mCallers));
-
-        stateLock.release();
-        RTSemEventWait(mObj->mZeroCallersSem, RT_INDEFINITE_WAIT);
-    }
-}
-
-/**
- *  Places the managed VirtualBoxBase object to the NotReady state.
- */
-AutoUninitSpan::~AutoUninitSpan()
-{
-    /* do nothing if already uninitialized */
-    if (mUninitDone)
-        return;
-
-    AutoWriteLock stateLock(mObj->mStateLock COMMA_LOCKVAL_SRC_POS);
-
-    Assert(mObj->mState == VirtualBoxBase::InUninit);
-
-    mObj->setState(VirtualBoxBase::NotReady);
-}
 
 ////////////////////////////////////////////////////////////////////////////////
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 51903)
@@ -7177,5 +7177,5 @@
 
     LogRel(("Console::powerDown(): A request to power off the VM has been issued (mMachineState=%s, InUninit=%d)\n",
-            Global::stringifyMachineState(mMachineState), autoCaller.state() == InUninit));
+            Global::stringifyMachineState(mMachineState), getObjectState().getState() == ObjectState::InUninit));
 
     /* Check if we need to power off the VM. In case of mVMPoweredOff=true, the
@@ -7320,5 +7320,5 @@
     /* If we are called from Console::uninit(), then try to destroy the VM even
      * on failure (this will most likely fail too, but what to do?..) */
-    if (RT_SUCCESS(vrc) || autoCaller.state() == InUninit)
+    if (RT_SUCCESS(vrc) || getObjectState().getState() == ObjectState::InUninit)
     {
         /* If the machine has a USB controller, release all USB devices
@@ -7518,6 +7518,6 @@
 {
     /* sanity check */
-    AssertReturn(AutoCaller(this).state() == InInit ||
-                 isWriteLockOnCurrentThread(), E_FAIL);
+    AssertReturn(   getObjectState().getState() == ObjectState::InInit
+                 || isWriteLockOnCurrentThread(), E_FAIL);
 
     LogFlowThisFunc(("Entering\n"));
@@ -7863,5 +7863,5 @@
      * 2) VM-(guest-)initiated power off. */
     AssertReturnVoid(   autoCaller.isOk()
-                     || autoCaller.state() == InUninit);
+                     || that->getObjectState().getState() == ObjectState::InUninit);
 
     switch (enmState)
Index: /trunk/src/VBox/Main/src-client/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 51903)
@@ -475,5 +475,5 @@
     AutoCaller autoCaller(this);
 
-    if (autoCaller.state() != Ready)
+    if (getObjectState().getState() != ObjectState::Ready)
     {
         /*
@@ -514,5 +514,5 @@
     HRESULT rc = S_OK;
 
-    if (autoCaller.state() == Ready)
+    if (getObjectState().getState() == ObjectState::Ready)
     {
         /* close() needs write lock */
@@ -536,5 +536,5 @@
         rc = unlockMachine(false /* aFinalRelease */, true /* aFromServer */);
     }
-    else if (autoCaller.state() == InUninit)
+    else if (getObjectState().getState() == ObjectState::InUninit)
     {
         /*
Index: /trunk/src/VBox/Main/src-server/HostImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/HostImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-server/HostImpl.cpp	(revision 51903)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2004-2013 Oracle Corporation
+ * Copyright (C) 2004-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -2972,6 +2972,6 @@
 {
 #ifdef VBOX_WITH_HOSTNETIF_API
-    AssertReturn(AutoCaller(this).state() == InInit ||
-                 isWriteLockOnCurrentThread(), E_FAIL);
+    AssertReturn(   getObjectState().getState() == ObjectState::InInit
+                 || isWriteLockOnCurrentThread(), E_FAIL);
 
     HostNetworkInterfaceList list, listCopy;
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 51903)
@@ -7436,5 +7436,5 @@
 
     /* just return false for inaccessible machines */
-    if (autoCaller.state() != Ready)
+    if (getObjectState().getState() != ObjectState::Ready)
         return false;
 
@@ -7469,5 +7469,5 @@
 
     /* just return false for inaccessible machines */
-    if (autoCaller.state() != Ready)
+    if (getObjectState().getState() != ObjectState::Ready)
         return false;
 
@@ -7599,5 +7599,5 @@
                         mData->mUuid.toString().c_str());
 
-    AssertReturn(autoCaller.state() == Ready, E_FAIL);
+    AssertReturn(getObjectState().getState() == ObjectState::Ready, E_FAIL);
 
     if (mData->mRegistered)
@@ -7853,6 +7853,6 @@
     AutoCaller autoCaller(this);
     AssertComRCReturnRC(autoCaller.rc());
-    AssertComRCReturn(autoCaller.state() == InInit ||
-                      autoCaller.state() == Limited, E_FAIL);
+    AssertComRCReturn(   getObjectState().getState() == ObjectState::InInit
+		      || getObjectState().getState() == ObjectState::Limited, E_FAIL);
 
     AssertReturn(!mData->mAccessible, E_FAIL);
@@ -7927,6 +7927,6 @@
     AutoCaller autoCaller(this);
     AssertComRCReturnVoid(autoCaller.rc());
-    AssertComRCReturnVoid(    autoCaller.state() == InUninit
-                           || autoCaller.state() == Limited);
+    AssertComRCReturnVoid(   getObjectState().getState() == ObjectState::InUninit
+                          || getObjectState().getState() == ObjectState::Limited);
 
     /* tell all our other child objects we've been uninitialized */
@@ -12716,5 +12716,5 @@
     AutoCaller autoCaller(this);
 
-    LogFlowThisFunc(("callerstate=%d\n", autoCaller.state()));
+    LogFlowThisFunc(("callerstate=%d\n", getObjectState().getState()));
     /*
      *  We don't assert below because it might happen that a non-direct session
Index: /trunk/src/VBox/Main/src-server/MediumImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-server/MediumImpl.cpp	(revision 51903)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2008-2013 Oracle Corporation
+ * Copyright (C) 2008-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -1375,5 +1375,5 @@
     {
         /* remove the caller reference we added in setFormat() */
-        m->formatObj->releaseCaller();
+        m->formatObj->getObjectState().releaseCaller();
         m->formatObj.setNull();
     }
@@ -6004,5 +6004,5 @@
      * no format is known yet */
     AssertReturn(    (!m->strFormat.isEmpty() && !m->formatObj.isNull())
-                  || (    autoCaller.state() == InInit
+                  || (    getObjectState().getState() == ObjectState::InInit
                        && m->state != MediumState_NotCreated
                        && m->id.isZero()
@@ -6177,5 +6177,5 @@
         /* reference the format permanently to prevent its unexpected
          * uninitialization */
-        HRESULT rc = m->formatObj->addCaller();
+        HRESULT rc = m->formatObj->getObjectState().addCaller(m->formatObj);
         AssertComRCReturnRC(rc);
 
Index: /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-server/SnapshotImpl.cpp	(revision 51903)
@@ -1797,5 +1797,5 @@
     AutoCaller autoCaller(this);
 
-    LogFlowThisFunc(("state=%d\n", autoCaller.state()));
+    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
     if (!autoCaller.isOk())
     {
@@ -2338,5 +2338,5 @@
     AutoCaller autoCaller(this);
 
-    LogFlowThisFunc(("state=%d\n", autoCaller.state()));
+    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
     if (!autoCaller.isOk())
     {
Index: /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 51902)
+++ /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 51903)
@@ -2272,7 +2272,7 @@
     if (SUCCEEDED((rc = autoCaller.rc())))
     {
-        if (autoCaller.state() != Ready)
+        if (getObjectState().getState() != ObjectState::Ready)
             LogWarningFunc(("VirtualBox has been uninitialized (state=%d), the event is discarded!\n",
-                            autoCaller.state()));
+                            getObjectState().getState()));
             // return S_OK
         else if (    (m->pAsyncEventQ)
@@ -4128,5 +4128,5 @@
     }
 
-    if (autoCaller.state() != InInit)
+    if (getObjectState().getState() != ObjectState::InInit)
     {
         rc = aMachine->i_prepareRegister();
@@ -4137,5 +4137,5 @@
     m->allMachines.addChild(aMachine);
 
-    if (autoCaller.state() != InInit)
+    if (getObjectState().getState() != ObjectState::InInit)
         rc = i_saveSettings();
 
@@ -4519,5 +4519,5 @@
                     continue;
                 /* object is already dead, no point in saving settings */
-                if (autoCaller.state() != Ready)
+                if (getObjectState().getState() != ObjectState::Ready)
                     continue;
                 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
@@ -4699,5 +4699,5 @@
     {
         LogWarningFunc(("VirtualBox has been uninitialized (state=%d), the callback event is discarded!\n",
-                        autoCaller.state()));
+                        mVirtualBox->getObjectState().getState()));
         /* We don't need mVirtualBox any more, so release it */
         mVirtualBox = NULL;
Index: /trunk/src/VBox/Main/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/testcase/Makefile.kmk	(revision 51902)
+++ /trunk/src/VBox/Main/testcase/Makefile.kmk	(revision 51903)
@@ -242,4 +242,5 @@
 	../src-client/MouseImpl.cpp \
 	../src-all/EventImpl.cpp \
+	../src-all/AutoCaller.cpp \
 	../src-all/VirtualBoxBase.cpp \
 	../src-all/VirtualBoxErrorInfoImpl.cpp \
