Index: /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 31019)
@@ -824,6 +824,5 @@
 
         // open a session
-        SessionType_T st;
-        CHECK_ERROR_BREAK(m, LockForSession(session, false /* fPermitShared */, &st));
+        CHECK_ERROR_BREAK(m, LockMachine(session, LockType_Write));
         fSessionOpened = true;
 
Index: /trunk/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp	(revision 31019)
@@ -150,6 +150,5 @@
         {
             RTPrintf ("Opening an existing session...\n");
-            SessionType_T st;
-            CHECK_ERROR_BREAK(m, LockForSession(session, true /* fPermitShared */, &st));
+            CHECK_ERROR_BREAK(m, LockMachine(session, LockType_Shared));
 
             ComPtr <IConsole> console;
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(revision 31019)
@@ -1864,6 +1864,5 @@
         CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]), ptrMachine.asOutParam()), 1);
 
-    SessionType_T st;
-    CHECK_ERROR_RET(ptrMachine, LockForSession(aSession, true /* fPermitShared */, &st), 1);
+    CHECK_ERROR_RET(ptrMachine, LockMachine(aSession, LockType_Shared), 1);
 
     /*
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 31019)
@@ -88,6 +88,5 @@
 
     /* open a session for the VM */
-    SessionType_T st;
-    CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
 
     do
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 31019)
@@ -286,6 +286,5 @@
         {
             /* open an existing session for VM */
-            SessionType_T st;
-            CHECK_ERROR_BREAK(machine, LockForSession(a->session, true /* fPermitShared */, &st));
+            CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Shared));
             // @todo r=dj assert that it's an existing session
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp	(revision 31019)
@@ -88,6 +88,5 @@
     {
         /* open a session for the VM - new or existing */
-        SessionType_T st;
-        CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+        CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
 
         /* get the mutable session machine */
@@ -154,6 +153,5 @@
     {
         /* open a session for the VM - new or existing */
-        SessionType_T st;
-        CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+        CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
 
         /* get the mutable session machine */
@@ -215,6 +213,5 @@
     {
         /* open a session for the VM - new or existing */
-        SessionType_T st;
-        CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+        CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
 
         /* get the mutable session machine */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 31019)
@@ -2135,6 +2135,5 @@
 
         /* open an existing session for the VM */
-        SessionType_T st;
-        rc = machine->LockForSession(a->session, true /* fPermitShared */, &st);
+        rc = machine->LockMachine(a->session, LockType_Shared);
         if (SUCCEEDED(rc))
             /* get the session machine */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp	(revision 31019)
@@ -418,6 +418,5 @@
         {
             /* we have to open a session for this task */
-            SessionType_T st;
-            CHECK_ERROR_BREAK(machine, LockForSession(a->session, false /* fPermitShared */, &st));
+            CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
             do
             {
@@ -453,6 +452,5 @@
         {
             /* we have to open a session for this task */
-            SessionType_T st;
-            CHECK_ERROR_BREAK(machine, LockForSession(a->session, false /* fPermitShared */, &st));
+            CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write));
             do
             {
@@ -728,6 +726,5 @@
 
             /* open an existing session for the VM */
-            SessionType_T st;
-            CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+            CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
             /* get the session machine */
             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
@@ -744,5 +741,5 @@
             /* open a session for the VM */
             SessionType_T st;
-            CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
+            CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
 
             /* get the mutable session machine */
@@ -794,6 +791,5 @@
 
             /* open an existing session for the VM */
-            SessionType_T st;
-            CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1);
+            CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
             /* get the session machine */
             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
@@ -809,6 +805,5 @@
         {
             /* open a session for the VM */
-            SessionType_T st;
-            CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
+            CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
 
             /* get the mutable session machine */
@@ -880,6 +875,5 @@
 
     /* open an existing session for the VM. */
-    SessionType_T st;
-    CHECK_ERROR(machine, LockForSession(a->session, true /* fPermitShared */, &st));
+    CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared));
     if (SUCCEEDED(rc))
     {
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 31019)
@@ -312,6 +312,5 @@
 
     /* open a session for the VM */
-    SessionType_T st;
-    CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
+    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
 
     /* get the mutable session machine */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp	(revision 31019)
@@ -240,6 +240,5 @@
     {
         /* we have to open a session for this task (new or shared) */
-        SessionType_T st;
-        rc = pMachine->LockForSession(a->session, true /* fPermitShared */, &st);
+        rc = pMachine->LockMachine(a->session, LockType_Shared);
         ComPtr<IConsole> console;
         CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp	(revision 31019)
@@ -173,7 +173,9 @@
 
     /* open a session for the VM (new or shared) */
-    SessionType_T type;
-    rc = machine->LockForSession(a->session, true /* fPermitShared */, &type);
-    bool fRunTime = (type == SessionType_Shared);
+    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
+    SessionType_T st;
+    CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), 1);
+    bool fRunTime = (st == SessionType_Shared);
+
     if (fRunTime && !RTStrICmp(pszType, "hdd"))
     {
@@ -755,6 +757,5 @@
 
     /* open a session for the VM */
-    SessionType_T st;
-    CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
+    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1);
 
     /* get the mutable session machine */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp	(revision 31019)
@@ -417,6 +417,5 @@
     {
         /* open a session for the VM */
-        SessionType_T st;
-        CHECK_ERROR_RET(cmd.mMachine, LockForSession(a->session, false /* fPermitShared */, &st), 1);
+        CHECK_ERROR_RET(cmd.mMachine, LockMachine(a->session, LockType_Write), 1);
         /* get the mutable session machine */
         a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam());
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 31019)
@@ -1365,6 +1365,5 @@
     AssertReleaseRC(vrc);
 
-    SessionType_T st;
-    rc = pMachine->LockForSession(session, false /* fPermitShared */, &st);
+    rc = pMachine->LockMachine(session, LockType_Write);
     if (FAILED(rc))
     {
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(revision 31019)
@@ -2179,6 +2179,7 @@
     if (!foundMachine.isNull())
     {
-        KSessionType t = foundMachine.LockForSession(session, aExisting /* fPermitShared */);
-        if (t == KSessionType_Shared)
+        foundMachine.LockMachine(session,
+                                 (aExisting) ? KLockType_Shared : KLockType_Write);
+        if (session.GetType() == KSessionType_Shared)
         {
             CMachine machine = session.GetMachine();
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMPreviewWindow.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMPreviewWindow.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMPreviewWindow.cpp	(revision 31019)
@@ -245,5 +245,5 @@
                 {
                     CVirtualBox vbox = vboxGlobal().virtualBox();
-                    m_machine.LockForSession(session, true /* fPermitShared */);
+                    m_machine.LockMachine(session, KLockType_Shared);
                     if (vbox.isOk())
                     {
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.cpp	(revision 31018)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.cpp	(revision 31019)
@@ -797,5 +797,5 @@
     CMachine foundMachine = vbox.GetMachine(id);
     if (!foundMachine.isNull())
-        foundMachine.LockForSession(session, false /* fPermitShared */);
+        foundMachine.LockMachine(session, KLockType_Write);
     if (!vbox.isOk())
     {
Index: /trunk/src/VBox/Main/ApplianceImplImport.cpp
===================================================================
--- /trunk/src/VBox/Main/ApplianceImplImport.cpp	(revision 31018)
+++ /trunk/src/VBox/Main/ApplianceImplImport.cpp	(revision 31019)
@@ -1233,5 +1233,5 @@
         {
             const MyHardDiskAttachment &mhda = *itM;
-            rc2 = mhda.pMachine->LockForSession(stack.pSession, false /* fPermitShared */, NULL);
+            rc2 = mhda.pMachine->LockMachine(stack.pSession, LockType_Write);
             if (SUCCEEDED(rc2))
             {
@@ -1760,5 +1760,5 @@
         {
             // to attach things we need to open a session for the new machine
-            rc = pNewMachine->LockForSession(stack.pSession, false /* fPermitShared */, NULL);
+            rc = pNewMachine->LockMachine(stack.pSession, LockType_Write);
             if (FAILED(rc)) DebugBreakThrow(rc);
             stack.fSessionOpen = true;
@@ -1872,5 +1872,5 @@
         {
             // to attach things we need to open a session for the new machine
-            rc = pNewMachine->LockForSession(stack.pSession, false /* fPermitShared */, NULL);
+            rc = pNewMachine->LockMachine(stack.pSession, LockType_Write);
             if (FAILED(rc)) DebugBreakThrow(rc);
             stack.fSessionOpen = true;
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 31018)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 31019)
@@ -2681,7 +2681,6 @@
  *  @note Locks objects!
  */
-STDMETHODIMP Machine::LockForSession(ISession *aSession,
-                                     BOOL fPermitShared,
-                                     SessionType_T *pSessionType)
+STDMETHODIMP Machine::LockMachine(ISession *aSession,
+                                  LockType_T lockType)
 {
     CheckComArgNotNull(aSession);
@@ -2700,13 +2699,273 @@
 
     /* get the IInternalSessionControl interface */
-    ComPtr<IInternalSessionControl> control = aSession;
-    ComAssertMsgRet(!!control, ("No IInternalSessionControl interface"),
+    ComPtr<IInternalSessionControl> pSessionControl = aSession;
+    ComAssertMsgRet(!!pSessionControl, ("No IInternalSessionControl interface"),
                     E_INVALIDARG);
 
-    rc = openSession(control);
-
-    if (FAILED(rc) && fPermitShared)
-        // try again @todo r=dj check exact error code!
-        rc = openExistingSession(control);
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (!mData->mRegistered)
+        return setError(E_UNEXPECTED,
+                        tr("The machine '%ls' is not registered"),
+                        mUserData->mName.raw());
+
+    LogFlowThisFunc(("mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));
+
+    /* Hack: in case the session is closing and there is a progress object
+     * which allows waiting for the session to be closed, take the opportunity
+     * and do a limited wait (max. 1 second). This helps a lot when the system
+     * is busy and thus session closing can take a little while. */
+    if (    mData->mSession.mState == SessionState_Unlocking
+        &&  mData->mSession.mProgress)
+    {
+        alock.release();
+        mData->mSession.mProgress->WaitForCompletion(1000);
+        alock.acquire();
+        LogFlowThisFunc(("after waiting: mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));
+    }
+
+    // try again now
+    if (    mData->mSession.mState == SessionState_Locked
+         || mData->mSession.mState == SessionState_Unlocking
+       )
+    {
+        // If the machine is write-locked already (i.e. SessionMachine exists) and
+        // caller permits sharing, then try to do that now
+        if (    (mData->mSession.mState == SessionState_Locked)
+             && (lockType == LockType_Shared)
+           )
+        {
+            ComAssertRet(!mData->mSession.mDirectControl.isNull(), E_FAIL);
+
+            // copy member variables before leaving lock
+            ComPtr<IInternalSessionControl> pDirectControl = mData->mSession.mDirectControl;
+            ComObjPtr<SessionMachine> pSessionMachine = mData->mSession.mMachine;
+            AssertReturn(!pSessionMachine.isNull(), E_FAIL);
+
+            /*
+             *  Leave the lock before calling the client process. It's safe here
+             *  since the only thing to do after we get the lock again is to add
+             *  the remote control to the list (which doesn't directly influence
+             *  anything).
+             */
+            alock.leave();
+
+            // get the console from the direct session (this is a remote call)
+            ComPtr<IConsole> pConsole;
+            LogFlowThisFunc(("Calling GetRemoteConsole()...\n"));
+            rc = pDirectControl->GetRemoteConsole(pConsole.asOutParam());
+            LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc));
+            if (FAILED(rc))
+                /* The failure may occur w/o any error info (from RPC), so provide one */
+                return setError(VBOX_E_VM_ERROR,
+                                tr("Failed to get a console object from the direct session (%Rrc)"), rc);
+
+            ComAssertRet(!pConsole.isNull(), E_FAIL);
+
+            /* attach the remote session to the machine */
+            LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));
+            rc = pSessionControl->AssignRemoteMachine(pSessionMachine, pConsole);
+            LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));
+
+            /* The failure may occur w/o any error info (from RPC), so provide one */
+            if (FAILED(rc))
+                return setError(VBOX_E_VM_ERROR,
+                                tr("Failed to assign the machine to the session (%Rrc)"),
+                                rc);
+            alock.enter();
+
+            /* need to revalidate the state after entering the lock again */
+            if (mData->mSession.mState != SessionState_Locked)
+            {
+                pSessionControl->Uninitialize();
+                return setError(VBOX_E_INVALID_SESSION_STATE,
+                                tr("The machine '%ls' was unlocked unexpectedly while attempting to share its session"),
+                                mUserData->mName.raw());
+            }
+
+            // add the caller's control to the list
+            mData->mSession.mRemoteControls.push_back(pSessionControl);
+        }
+        else
+            // still unlocking, or caller has not permitted sharing:
+            return setError(VBOX_E_INVALID_OBJECT_STATE,
+                            tr("The machine '%ls' is already locked for a session (or being unlocked)"),
+                            mUserData->mName.raw());
+    }
+    else
+    {
+        // no lock exists or sharing not permitted: then create the session machine
+
+        /* may not be busy */
+        AssertReturn(!Global::IsOnlineOrTransient(mData->mMachineState), E_FAIL);
+
+        // get the caller's session PID
+        RTPROCESS pid = NIL_RTPROCESS;
+        AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS));
+        pSessionControl->GetPID((ULONG*)&pid);
+        Assert(pid != NIL_RTPROCESS);
+
+        if (mData->mSession.mState == SessionState_Spawning)
+        {
+            /* This machine is awaiting for a spawning session to be opened, so
+             * reject any other open attempts from processes other than one
+             * started by #openRemoteSession(). */
+
+            LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n", mData->mSession.mPid, mData->mSession.mPid));
+            LogFlowThisFunc(("session.pid=%d(0x%x)\n", pid, pid));
+
+            if (mData->mSession.mPid != pid)
+                return setError(E_ACCESSDENIED,
+                                tr("An unexpected process (PID=0x%08X) has tried to lock the "
+                                   "machine '%ls', while only the process started by launchVMProcess (PID=0x%08X) is allowed"),
+                                pid, mUserData->mName.raw(), mData->mSession.mPid);
+        }
+
+        // create the mutable SessionMachine from the current machine
+        ComObjPtr<SessionMachine> sessionMachine;
+        sessionMachine.createObject();
+        rc = sessionMachine->init(this);
+        AssertComRC(rc);
+
+        /* NOTE: doing return from this function after this point but
+         * before the end is forbidden since it may call SessionMachine::uninit()
+         * (through the ComObjPtr's destructor) which requests the VirtualBox write
+         * lock while still holding the Machine lock in alock so that a deadlock
+         * is possible due to the wrong lock order. */
+
+        if (SUCCEEDED(rc))
+        {
+            /*
+             *  Set the session state to Spawning to protect against subsequent
+             *  attempts to open a session and to unregister the machine after
+             *  we leave the lock.
+             */
+            SessionState_T origState = mData->mSession.mState;
+            mData->mSession.mState = SessionState_Spawning;
+
+            /*
+             *  Leave the lock before calling the client process -- it will call
+             *  Machine/SessionMachine methods. Leaving the lock here is quite safe
+             *  because the state is Spawning, so that openRemotesession() and
+             *  openExistingSession() calls will fail. This method, called before we
+             *  enter the lock again, will fail because of the wrong PID.
+             *
+             *  Note that mData->mSession.mRemoteControls accessed outside
+             *  the lock may not be modified when state is Spawning, so it's safe.
+             */
+            alock.leave();
+
+            LogFlowThisFunc(("Calling AssignMachine()...\n"));
+            rc = pSessionControl->AssignMachine(sessionMachine);
+            LogFlowThisFunc(("AssignMachine() returned %08X\n", rc));
+
+            /* The failure may occur w/o any error info (from RPC), so provide one */
+            if (FAILED(rc))
+                setError(VBOX_E_VM_ERROR,
+                         tr("Failed to assign the machine to the session (%Rrc)"), rc);
+
+            if (    SUCCEEDED(rc)
+                 && origState == SessionState_Spawning
+               )
+            {
+                /* complete the remote session initialization */
+
+                /* get the console from the direct session */
+                ComPtr<IConsole> console;
+                rc = pSessionControl->GetRemoteConsole(console.asOutParam());
+                ComAssertComRC(rc);
+
+                if (SUCCEEDED(rc) && !console)
+                {
+                    ComAssert(!!console);
+                    rc = E_FAIL;
+                }
+
+                /* assign machine & console to the remote session */
+                if (SUCCEEDED(rc))
+                {
+                    /*
+                     *  after openRemoteSession(), the first and the only
+                     *  entry in remoteControls is that remote session
+                     */
+                    LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));
+                    rc = mData->mSession.mRemoteControls.front()->AssignRemoteMachine(sessionMachine, console);
+                    LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));
+
+                    /* The failure may occur w/o any error info (from RPC), so provide one */
+                    if (FAILED(rc))
+                        setError(VBOX_E_VM_ERROR,
+                                 tr("Failed to assign the machine to the remote session (%Rrc)"), rc);
+                }
+
+                if (FAILED(rc))
+                    pSessionControl->Uninitialize();
+            }
+
+            /* enter the lock again */
+            alock.enter();
+
+            /* Restore the session state */
+            mData->mSession.mState = origState;
+        }
+
+        /* finalize spawning anyway (this is why we don't return on errors above) */
+        if (mData->mSession.mState == SessionState_Spawning)
+        {
+            /* Note that the progress object is finalized later */
+            /** @todo Consider checking mData->mSession.mProgress for cancellation
+             *        around here.  */
+
+            /* We don't reset mSession.mPid here because it is necessary for
+             * SessionMachine::uninit() to reap the child process later. */
+
+            if (FAILED(rc))
+            {
+                /* Close the remote session, remove the remote control from the list
+                 * and reset session state to Closed (@note keep the code in sync
+                 * with the relevant part in openSession()). */
+
+                Assert(mData->mSession.mRemoteControls.size() == 1);
+                if (mData->mSession.mRemoteControls.size() == 1)
+                {
+                    ErrorInfoKeeper eik;
+                    mData->mSession.mRemoteControls.front()->Uninitialize();
+                }
+
+                mData->mSession.mRemoteControls.clear();
+                mData->mSession.mState = SessionState_Unlocked;
+            }
+        }
+        else
+        {
+            /* memorize PID of the directly opened session */
+            if (SUCCEEDED(rc))
+                mData->mSession.mPid = pid;
+        }
+
+        if (SUCCEEDED(rc))
+        {
+            /* memorize the direct session control and cache IUnknown for it */
+            mData->mSession.mDirectControl = pSessionControl;
+            mData->mSession.mState = SessionState_Locked;
+            /* associate the SessionMachine with this Machine */
+            mData->mSession.mMachine = sessionMachine;
+
+            /* request an IUnknown pointer early from the remote party for later
+             * identity checks (it will be internally cached within mDirectControl
+             * at least on XPCOM) */
+            ComPtr<IUnknown> unk = mData->mSession.mDirectControl;
+            NOREF(unk);
+        }
+
+        /* Leave the lock since SessionMachine::uninit() locks VirtualBox which
+         * would break the lock order */
+        alock.leave();
+
+        /* uninitialize the created session machine on failure */
+        if (FAILED(rc))
+            sessionMachine->uninit();
+
+    }
 
     if (SUCCEEDED(rc))
@@ -2720,8 +2979,4 @@
         /* fire an event */
         mParent->onSessionStateChange(getId(), SessionState_Locked);
-
-        // return session type to caller
-        if (pSessionType)
-            aSession->COMGETTER(Type)(pSessionType);
     }
 
@@ -5354,222 +5609,4 @@
 
 /**
- *  @note Locks this object for writing, calls the client process (outside the
- *        lock).
- */
-HRESULT Machine::openSession(IInternalSessionControl *aControl)
-{
-    LogFlowThisFuncEnter();
-
-    AssertReturn(aControl, E_FAIL);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc()))
-        return autoCaller.rc();
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (!mData->mRegistered)
-        return setError(E_UNEXPECTED,
-                        tr("The machine '%ls' is not registered"),
-                        mUserData->mName.raw());
-
-    LogFlowThisFunc(("mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));
-
-    /* Hack: in case the session is closing and there is a progress object
-     * which allows waiting for the session to be closed, take the opportunity
-     * and do a limited wait (max. 1 second). This helps a lot when the system
-     * is busy and thus session closing can take a little while. */
-    if (    mData->mSession.mState == SessionState_Unlocking
-        &&  mData->mSession.mProgress)
-    {
-        alock.leave();
-        mData->mSession.mProgress->WaitForCompletion(1000);
-        alock.enter();
-        LogFlowThisFunc(("after waiting: mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));
-    }
-
-    if (    mData->mSession.mState == SessionState_Locked
-         || mData->mSession.mState == SessionState_Unlocking
-       )
-        return setError(VBOX_E_INVALID_OBJECT_STATE,
-                        tr("The machine '%ls' is already locked for a session (or being unlocked)"),
-                        mUserData->mName.raw());
-
-    /* may not be busy */
-    AssertReturn(!Global::IsOnlineOrTransient(mData->mMachineState), E_FAIL);
-
-    /* get the session PID */
-    RTPROCESS pid = NIL_RTPROCESS;
-    AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS));
-    aControl->GetPID((ULONG *) &pid);
-    Assert(pid != NIL_RTPROCESS);
-
-    if (mData->mSession.mState == SessionState_Spawning)
-    {
-        /* This machine is awaiting for a spawning session to be opened, so
-         * reject any other open attempts from processes other than one
-         * started by #openRemoteSession(). */
-
-        LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n",
-                          mData->mSession.mPid, mData->mSession.mPid));
-        LogFlowThisFunc(("session.pid=%d(0x%x)\n", pid, pid));
-
-        if (mData->mSession.mPid != pid)
-            return setError(E_ACCESSDENIED,
-                            tr("An unexpected process (PID=0x%08X) has tried to lock the "
-                               "machine '%ls', while only the process started by launchVMProcess (PID=0x%08X) is allowed"),
-                            pid, mUserData->mName.raw(), mData->mSession.mPid);
-    }
-
-    /* create a SessionMachine object */
-    ComObjPtr<SessionMachine> sessionMachine;
-    sessionMachine.createObject();
-    HRESULT rc = sessionMachine->init(this);
-    AssertComRC(rc);
-
-    /* NOTE: doing return from this function after this point but
-     * before the end is forbidden since it may call SessionMachine::uninit()
-     * (through the ComObjPtr's destructor) which requests the VirtualBox write
-     * lock while still holding the Machine lock in alock so that a deadlock
-     * is possible due to the wrong lock order. */
-
-    if (SUCCEEDED(rc))
-    {
-        /*
-         *  Set the session state to Spawning to protect against subsequent
-         *  attempts to open a session and to unregister the machine after
-         *  we leave the lock.
-         */
-        SessionState_T origState = mData->mSession.mState;
-        mData->mSession.mState = SessionState_Spawning;
-
-        /*
-         *  Leave the lock before calling the client process -- it will call
-         *  Machine/SessionMachine methods. Leaving the lock here is quite safe
-         *  because the state is Spawning, so that openRemotesession() and
-         *  openExistingSession() calls will fail. This method, called before we
-         *  enter the lock again, will fail because of the wrong PID.
-         *
-         *  Note that mData->mSession.mRemoteControls accessed outside
-         *  the lock may not be modified when state is Spawning, so it's safe.
-         */
-        alock.leave();
-
-        LogFlowThisFunc(("Calling AssignMachine()...\n"));
-        rc = aControl->AssignMachine(sessionMachine);
-        LogFlowThisFunc(("AssignMachine() returned %08X\n", rc));
-
-        /* The failure may occur w/o any error info (from RPC), so provide one */
-        if (FAILED(rc))
-            setError(VBOX_E_VM_ERROR,
-                tr("Failed to assign the machine to the session (%Rrc)"), rc);
-
-        if (SUCCEEDED(rc) && origState == SessionState_Spawning)
-        {
-            /* complete the remote session initialization */
-
-            /* get the console from the direct session */
-            ComPtr<IConsole> console;
-            rc = aControl->GetRemoteConsole(console.asOutParam());
-            ComAssertComRC(rc);
-
-            if (SUCCEEDED(rc) && !console)
-            {
-                ComAssert(!!console);
-                rc = E_FAIL;
-            }
-
-            /* assign machine & console to the remote session */
-            if (SUCCEEDED(rc))
-            {
-                /*
-                 *  after openRemoteSession(), the first and the only
-                 *  entry in remoteControls is that remote session
-                 */
-                LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));
-                rc = mData->mSession.mRemoteControls.front()->
-                    AssignRemoteMachine(sessionMachine, console);
-                LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));
-
-                /* The failure may occur w/o any error info (from RPC), so provide one */
-                if (FAILED(rc))
-                    setError(VBOX_E_VM_ERROR,
-                             tr("Failed to assign the machine to the remote session (%Rrc)"), rc);
-            }
-
-            if (FAILED(rc))
-                aControl->Uninitialize();
-        }
-
-        /* enter the lock again */
-        alock.enter();
-
-        /* Restore the session state */
-        mData->mSession.mState = origState;
-    }
-
-    /* finalize spawning anyway (this is why we don't return on errors above) */
-    if (mData->mSession.mState == SessionState_Spawning)
-    {
-        /* Note that the progress object is finalized later */
-        /** @todo Consider checking mData->mSession.mProgress for cancellation
-         *        around here.  */
-
-        /* We don't reset mSession.mPid here because it is necessary for
-         * SessionMachine::uninit() to reap the child process later. */
-
-        if (FAILED(rc))
-        {
-            /* Close the remote session, remove the remote control from the list
-             * and reset session state to Closed (@note keep the code in sync
-             * with the relevant part in openSession()). */
-
-            Assert(mData->mSession.mRemoteControls.size() == 1);
-            if (mData->mSession.mRemoteControls.size() == 1)
-            {
-                ErrorInfoKeeper eik;
-                mData->mSession.mRemoteControls.front()->Uninitialize();
-            }
-
-            mData->mSession.mRemoteControls.clear();
-            mData->mSession.mState = SessionState_Unlocked;
-        }
-    }
-    else
-    {
-        /* memorize PID of the directly opened session */
-        if (SUCCEEDED(rc))
-            mData->mSession.mPid = pid;
-    }
-
-    if (SUCCEEDED(rc))
-    {
-        /* memorize the direct session control and cache IUnknown for it */
-        mData->mSession.mDirectControl = aControl;
-        mData->mSession.mState = SessionState_Locked;
-        /* associate the SessionMachine with this Machine */
-        mData->mSession.mMachine = sessionMachine;
-
-        /* request an IUnknown pointer early from the remote party for later
-         * identity checks (it will be internally cached within mDirectControl
-         * at least on XPCOM) */
-        ComPtr<IUnknown> unk = mData->mSession.mDirectControl;
-        NOREF(unk);
-    }
-
-    /* Leave the lock since SessionMachine::uninit() locks VirtualBox which
-     * would break the lock order */
-    alock.leave();
-
-    /* uninitialize the created session machine on failure */
-    if (FAILED(rc))
-        sessionMachine->uninit();
-
-    LogFlowThisFunc(("rc=%Rhrc\n", rc));
-    LogFlowThisFuncLeave();
-    return rc;
-}
-
-/**
  *  @note Locks this object for writing, calls the client process
  *        (inside the lock).
@@ -5797,89 +5834,4 @@
     mData->mSession.mState = SessionState_Spawning;
     mData->mSession.mType = strType;
-
-    LogFlowThisFuncLeave();
-    return S_OK;
-}
-
-
-/**
- *  @note Locks this object for writing, calls the client process
- *        (outside the lock).
- */
-HRESULT Machine::openExistingSession(IInternalSessionControl *aControl)
-{
-    LogFlowThisFuncEnter();
-
-    AssertReturn(aControl, E_FAIL);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-    if (!mData->mRegistered)
-        return setError(E_UNEXPECTED,
-                        tr("The machine '%ls' is not registered"),
-                        mUserData->mName.raw());
-
-    LogFlowThisFunc(("mSession.state=%s\n", Global::stringifySessionState(mData->mSession.mState)));
-
-    if (mData->mSession.mState != SessionState_Locked)
-        return setError(VBOX_E_INVALID_SESSION_STATE,
-                        tr("The machine '%ls' is not currently locked for a session"),
-                        mUserData->mName.raw());
-
-    ComAssertRet(!mData->mSession.mDirectControl.isNull(), E_FAIL);
-
-    // copy member variables before leaving lock
-    ComPtr<IInternalSessionControl> pDirectControl = mData->mSession.mDirectControl;
-    ComObjPtr<SessionMachine> pSessionMachine = mData->mSession.mMachine;
-    AssertReturn(!pSessionMachine.isNull(), E_FAIL);
-
-    /*
-     *  Leave the lock before calling the client process. It's safe here
-     *  since the only thing to do after we get the lock again is to add
-     *  the remote control to the list (which doesn't directly influence
-     *  anything).
-     */
-    alock.leave();
-
-    // get the console from the direct session (this is a remote call)
-    ComPtr<IConsole> pConsole;
-    LogFlowThisFunc(("Calling GetRemoteConsole()...\n"));
-    HRESULT rc = pDirectControl->GetRemoteConsole(pConsole.asOutParam());
-    LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc));
-    if (FAILED (rc))
-        /* The failure may occur w/o any error info (from RPC), so provide one */
-        return setError(VBOX_E_VM_ERROR,
-            tr("Failed to get a console object from the direct session (%Rrc)"), rc);
-
-    ComAssertRet(!pConsole.isNull(), E_FAIL);
-
-    /* attach the remote session to the machine */
-    LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));
-    rc = aControl->AssignRemoteMachine(pSessionMachine, pConsole);
-    LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));
-
-    /* The failure may occur w/o any error info (from RPC), so provide one */
-    if (FAILED(rc))
-        return setError(VBOX_E_VM_ERROR,
-                        tr("Failed to assign the machine to the session (%Rrc)"),
-                        rc);
-
-    alock.enter();
-
-    /* need to revalidate the state after entering the lock again */
-    if (mData->mSession.mState != SessionState_Locked)
-    {
-        aControl->Uninitialize();
-
-        return setError(VBOX_E_INVALID_SESSION_STATE,
-                        tr("The machine '%ls' is not currently locked for a session"),
-                        mUserData->mName.raw());
-    }
-
-    /* store the control in the list */
-    mData->mSession.mRemoteControls.push_back(aControl);
 
     LogFlowThisFuncLeave();
Index: /trunk/src/VBox/Main/SessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/SessionImpl.cpp	(revision 31018)
+++ /trunk/src/VBox/Main/SessionImpl.cpp	(revision 31019)
@@ -278,5 +278,5 @@
     AssertReturn(mState != SessionState_Unlocked, VBOX_E_INVALID_VM_STATE);
 
-    AssertMsgReturn(mType == SessionType_Direct && !!mConsole,
+    AssertMsgReturn(mType == SessionType_WriteLock && !!mConsole,
                     ("This is not a direct session!\n"),
                     VBOX_E_INVALID_OBJECT_STATE);
@@ -345,5 +345,5 @@
     if (SUCCEEDED(rc))
     {
-        mType = SessionType_Direct;
+        mType = SessionType_WriteLock;
         mState = SessionState_Locked;
     }
@@ -458,5 +458,5 @@
 
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     AssertReturn(!mControl.isNull(), E_FAIL);
@@ -522,5 +522,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onNetworkAdapterChange(networkAdapter, changeAdapter);
@@ -536,5 +536,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onSerialPortChange(serialPort);
@@ -550,5 +550,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onParallelPortChange(parallelPort);
@@ -564,5 +564,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onStorageControllerChange();
@@ -578,5 +578,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onMediumChange(aMediumAttachment, aForce);
@@ -592,5 +592,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onCPUChange(aCPU, aRemove);
@@ -606,5 +606,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onVRDPServerChange(aRestart);
@@ -620,5 +620,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onUSBControllerChange();
@@ -634,5 +634,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onSharedFolderChange(aGlobal);
@@ -650,5 +650,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onUSBDeviceAttach(aDevice, aError, aMaskedIfs);
@@ -665,5 +665,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     return mConsole->onUSBDeviceDetach(aId, aError);
@@ -677,5 +677,5 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
 
     if (mState != SessionState_Locked)
@@ -704,5 +704,5 @@
                         tr("Machine is not locked by session (session state: %s)."),
                         Global::stringifySessionState(mState));
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     CheckComArgStrNotEmptyOrNull(aName);
     if (!aIsSetter && !VALID_PTR(aRetValue))
@@ -741,5 +741,5 @@
                         tr("Machine is not locked by session (session state: %s)."),
                         Global::stringifySessionState(mState));
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     if (!VALID_PTR(aPatterns) && (aPatterns != NULL))
         return E_POINTER;
@@ -777,5 +777,5 @@
                         tr("Machine is not locked by session (session state: %s)."),
                         Global::stringifySessionState(mState));
-    AssertReturn(mType == SessionType_Direct, VBOX_E_INVALID_OBJECT_STATE);
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     CheckComArgNotNull(aMediumAttachment);
     CheckComArgSafeArrayNotNull(aChildrenToReparent);
@@ -847,5 +847,5 @@
     mState = SessionState_Unlocking;
 
-    if (mType == SessionType_Direct)
+    if (mType == SessionType_WriteLock)
     {
         mConsole->uninit();
@@ -894,5 +894,5 @@
          *        VirtualBoxBase::addCaller.
          */
-        if (mType != SessionType_Direct && (rc == E_UNEXPECTED || rc == E_ACCESSDENIED))
+        if (mType != SessionType_WriteLock && (rc == E_UNEXPECTED || rc == E_ACCESSDENIED))
             rc = S_OK;
 
@@ -902,5 +902,5 @@
     mControl.setNull();
 
-    if (mType == SessionType_Direct)
+    if (mType == SessionType_WriteLock)
     {
         releaseIPCSemaphore();
Index: /trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 31018)
+++ /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 31019)
@@ -3723,5 +3723,5 @@
 /**
  *  Thread function that watches the termination of all client processes
- *  that have opened sessions using IMachine::LockForSession()
+ *  that have opened sessions using IMachine::LockMachine()
  */
 // static
Index: /trunk/src/VBox/Main/glue/glue-java.xsl
===================================================================
--- /trunk/src/VBox/Main/glue/glue-java.xsl	(revision 31018)
+++ /trunk/src/VBox/Main/glue/glue-java.xsl	(revision 31019)
@@ -2497,5 +2497,5 @@
     {
         ISession s = getSessionObject();
-        m.lockForSession(s, true /* fPermitShared */);
+        m.lockMachine(s, LockType.Shared);
         return s;
     }
@@ -3459,5 +3459,5 @@
     {
         ISession s = getSessionObject();
-        m.lockForSession(s, true /* fPermitShared */ );
+        m.lockMachine(s, LockType.Shared);
         return s;
     }
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 31018)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 31019)
@@ -818,5 +818,5 @@
         currently locked for this session, and the mutable machine object
         can be found in the <link to="ISession::machine"/> attribute
-        (see <link to="IMachine::lockForSession" /> for details).
+        (see <link to="IMachine::lockMachine" /> for details).
       </desc>
     </const>
@@ -825,5 +825,5 @@
         A new process is being spawned for the machine as a result of
         <link to="IMachine::launchVMProcess"/> call. This state also occurs
-        as a short transient state during an <link to="IMachine::lockForSession"/>
+        as a short transient state during an <link to="IMachine::lockMachine"/>
         call.
       </desc>
@@ -906,4 +906,19 @@
 
   <enum
+   name="LockType"
+   uuid="138b53f8-db4b-47c5-b32b-4ef52f769413"
+  >
+    <desc>
+      Used with <link to="IMachine::lockMachine" />.
+    </desc>
+    <const name="Write" value="2">
+      <desc>Lock the machine for writing.</desc>
+    </const>
+    <const name="Shared" value="1">
+      <desc>Request only a shared read lock for remote-controlling the machine.</desc>
+    </const>
+  </enum>
+
+  <enum
     name="SessionType"
     uuid="A13C02CB-0C2C-421E-8317-AC0E8AAA153A"
@@ -917,20 +932,20 @@
       <desc>Null value (never used by the API).</desc>
     </const>
-    <const name="Direct"                value="1">
-      <desc>
-        Direct session
-        (used with <link to="IMachine::lockForSession"/>)
+    <const name="WriteLock"             value="1">
+      <desc>
+        Session has acquired an exclusive write lock on a machine
+        using <link to="IMachine::lockMachine"/>.
       </desc>
     </const>
     <const name="Remote"                value="2">
       <desc>
-        Remote VM process
-        (opened by <link to="IMachine::launchVMProcess"/>)
+        Session has launched a VM process using
+        <link to="IMachine::launchVMProcess"/>
       </desc>
     </const>
     <const name="Shared"                value="3">
       <desc>
-        Shared session; remote link to an existing direct session opened
-        by <link to="IMachine::lockForSession"/> with fPermitShared = true
+        Session has obtained a link to another session using
+        <link to="IMachine::lockMachine"/>
       </desc>
     </const>
@@ -3655,5 +3670,5 @@
 
       In order to change a machine setting, a session for this machine must be
-      opened using one of the <link to="IMachine::lockForSession" /> or
+      opened using one of the <link to="IMachine::lockMachine" /> or
       <link to="IMachine::launchVMProcess"/> methods. After the
       machine has been successfully locked for a session, a mutable machine object
@@ -3997,6 +4012,6 @@
         same value as passed to the
         <link to="IMachine::launchVMProcess"/> method in the
-        @a type parameter. If the session was opened directly using
-        <link to="IMachine::lockForSession" />, or if
+        @a type parameter. If the session was used with
+        <link to="IMachine::lockMachine" />, or if
         <link to="#sessionState"/> is SessionClosed, the value of this
         attribute is an empty string.
@@ -4007,10 +4022,8 @@
       <desc>
         Identifier of the session process. This attribute contains the
-        platform-dependent identifier of the process that has opened a
-        direct session for this machine using the
-        <link to="IMachine::lockForSession" /> call. The returned value
-        is only valid if <link to="#sessionState"/> is SessionOpen or
-        SessionClosing (i.e. a session is currently open or being
-        closed) by the time this property is read.
+        platform-dependent identifier of the process whose session was
+        used with <link to="IMachine::lockMachine" /> call. The returned
+        value is only valid if <link to="#sessionState"/> is Locked or
+        Unlocking by the time this property is read.
       </desc>
     </attribute>
@@ -4193,42 +4206,66 @@
     </attribute>
 
-    <method name="lockForSession">
+    <method name="lockMachine">
       <desc>
         Locks the machine for the given session to enable the caller
-        to make changes to the machine or start the VM.
-
-        A single machine can only be locked for a single sesseion
-        at a time, protecting the VM from being manipulated by
-        conflicting actions from different processes. Only after this
-        method has been called, one can change all VM settings
-        or execute the VM in the process space of the session object.
-        See <link to="ISession">ISession</link> for details.
-
-        Locking the machine for a session creates a second copy of
-        the IMachine object. It is this second object upon which
-        changes can be made; in VirtualBox terminology, the second
-        copy is "mutable". It is only this second, mutable machine
-        object upon which you can call methods that change the
-        machine state. After having called this method, you can
-        obtain this second, mutable machine object using the
-        <link to="ISession::machine" /> attribute. This way, you can
-        also get access to the <link to="IConsole" /> object which
-        controls VM execution.
-
-        <note>Unless you are writing a new VM frontend, you will not
-        want to execute a VM in the current process. To spawn a new
-        process that executes a VM, use <link to="IMachine::launchVMProcess" />
-        instead.</note>
-
-        One must always call <link to="ISession::close" /> to release the
-        lock on the machine, or the machine's state will eventually be
-        set to "Aborted".
-
-        In other words, to change settings on a machine, the following
-        sequence is typically performed:
+        to make changes to the machine or start the VM or control
+        VM execution.
+
+        There are two ways to lock a machine for such uses:
+
+        <ul>
+          <li>If you want to make changes to the machine settings,
+            you must obtain an exclusive write lock on the machine
+            by setting @a lockType to @c Write.
+
+            This will only succeed if no other process has locked
+            the machine to prevent conflicting changes. Only after
+            an exclusive write lock has been obtained using this method, one
+            can change all VM settings or execute the VM in the process
+            space of the session object. (Note that the latter is only of
+            interest if you actually want to write a new front-end for
+            virtual machines; but this API gets called internally by
+            the existing front-ends such as VBoxHeadless and the VirtualBox
+            GUI to acquire a write lock on the machine that they are running.)
+
+            On success, write-locking the machine for a session creates
+            a second copy of the IMachine object. It is this second object
+            upon which changes can be made; in VirtualBox terminology, the
+            second copy is "mutable". It is only this second, mutable machine
+            object upon which you can call methods that change the
+            machine state. After having called this method, you can
+            obtain this second, mutable machine object using the
+            <link to="ISession::machine" /> attribute.
+          </li>
+          <li>If you only want to check the machine state or control
+            machine execution without actually changing machine
+            settings (e.g. to get access to VM statistics or take
+            a snapshot or save the machine state), then set the
+            @a lockType argument to @c Shared.
+
+            If no other session has obtained a lock, you will obtain an
+            exclusive write lock as described above. However, if another
+            session has already obtained such a lock, then a link to that
+            existing session will be established which allows you
+            to control that existing session.
+
+            To find out which type of lock was obtained, you can
+            inspect <link to="ISession::type" />, which will have been
+            set to either @c WriteLock or @c Shared.
+          </li>
+        </ul>
+
+        In either case, you can get access to the <link to="IConsole" />
+        object which controls VM execution.
+
+        Also in all of the above cases, one must always call <link to="ISession::close" />
+        to release the lock on the machine, or the machine's state will
+        eventually be set to "Aborted".
+
+        To change settings on a machine, the following sequence is typically
+        performed:
 
         <ol>
-          <li>Call this method (openSession) to have a machine locked for
-            the current session.</li>
+          <li>Call this method to obtain an exclusive write lock for the current session.</li>
 
           <li>Obtain a mutable IMachine object from <link to="ISession::machine" />.</li>
@@ -4241,20 +4278,4 @@
         </ol>
 
-        If the @a fPermitShared parameter is set to true, this method will also
-        succeed on a machine which has already been locked by another session.
-        The caller will then be attached to that existing session, and its own
-        session will be marked as "Shared". While not all machine settings can
-        be changed in that case, an IConsole object will still be created which
-        provides to the caller some level of control over the VM execution, for
-        example to pause the machine. The number of such shared sessions per
-        machine is not limited by the API.
-
-        The return value will then indicate whether a direct session was opened
-        (<link to="SessionType::Direct" />) or whether an existing direct session
-        was shared ((<link to="SessionType::Shared" />).
-
-        If the @a fPermitShared parameter is @c false, then this can only
-        possibly return <link to="SessionType::Direct" />.
-
         <result name="E_UNEXPECTED">
           Virtual machine not registered.
@@ -4275,11 +4296,9 @@
         </desc>
       </param>
-      <param name="fPermitShared" type="boolean" dir="in">
-        <desc>
-          Whether to allow for sharing a direct session remotely.
-        </desc>
-      </param>
-      <param name="sessionType" type="SessionType" dir="return">
-        <desc>
+      <param name="lockType" type="LockType" dir="in">
+        <desc>
+          If set to @c Write, then attempt to acquire an exclusive write lock or fail.
+          If set to @c Shared, then either acquire an exclusive write lock or establish
+          a link to an existing session.
         </desc>
       </param>
@@ -4312,5 +4331,5 @@
         object which can be used to control machine execution, but it cannot
         be used to change all VM settings which would be available after
-        a <link to="#lockForSession" /> call.
+        a <link to="#lockMachine" /> call.
 
         As with all <link to="ISession" /> objects, it is recommended to call
@@ -5924,5 +5943,5 @@
 
       A console object gets created when a machine has been locked for a
-      particular session (client process) using <link to="IMachine::lockForSession" />
+      particular session (client process) using <link to="IMachine::lockMachine" />
       or <link to="IMachine::launchVMProcess"/>. The console object can
       then be found in the session's <link to="ISession::console" /> attribute.
@@ -12755,5 +12774,5 @@
       <ul>
         <li>To alter machine settings, one needs to lock a machine for a given session
-          (client process) by calling <link to="IMachine::lockForSession"/>. While a
+          (client process) by calling <link to="IMachine::lockMachine"/>. While a
           machine is thus locked, no any other process may lock the machine again.
 
@@ -12823,5 +12842,5 @@
         Calling this method is eventually required every time a machine has been
         locked for a particular session using the <link to="IMachine::launchVMProcess" />
-        or <link to="IMachine::lockForSession" />) calls. Otherwise the state of
+        or <link to="IMachine::lockMachine" />) calls. Otherwise the state of
         the machine will be set to <link to="MachineState_Aborted" /> on the
         server, and changes made to the machine settings will be lost.
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 31018)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 31019)
@@ -115,5 +115,5 @@
         struct Session
         {
-            /** Control of the direct session opened by lockForSession() */
+            /** Control of the direct session opened by lockMachine() */
             ComPtr<IInternalSessionControl> mDirectControl;
 
@@ -455,5 +455,5 @@
 
     // IMachine methods
-    STDMETHOD(LockForSession)(ISession *aSession, BOOL fPermitShared, SessionType_T *sessionType);
+    STDMETHOD(LockMachine)(ISession *aSession, LockType_T lockType);
     STDMETHOD(LaunchVMProcess)(ISession *aSession,  IN_BSTR aType, IN_BSTR aEnvironment, IProgress **aProgress);
 
@@ -627,9 +627,7 @@
     Utf8Str queryLogFilename(ULONG idx);
 
-    HRESULT openSession(IInternalSessionControl *aControl);
     HRESULT openRemoteSession(IInternalSessionControl *aControl,
                               IN_BSTR aType, IN_BSTR aEnvironment,
                               ProgressProxy *aProgress);
-    HRESULT openExistingSession(IInternalSessionControl *aControl);
 
     HRESULT getDirectControl(ComPtr<IInternalSessionControl> *directControl)
Index: /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
===================================================================
--- /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 31018)
+++ /trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp	(revision 31019)
@@ -266,5 +266,5 @@
         }
 
-        machine->LockForSession(session, false /* fPermitShared */, NULL);
+        machine->LockMachine(session, LockType_Write);
         if (NS_FAILED(rc))
         {
