Index: /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 51676)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 51677)
@@ -74,4 +74,18 @@
 // Constructor / destructor
 //
+
+VBoxSDLFB::VBoxSDLFB()
+{
+}
+
+HRESULT VBoxSDLFB::FinalConstruct()
+{
+    return 0;
+}
+
+void VBoxSDLFB::FinalRelease()
+{
+    return;
+}
 
 /**
@@ -87,5 +101,5 @@
  * @param iFixedHeight   fixed SDL height (-1 means not set)
  */
-VBoxSDLFB::VBoxSDLFB(uint32_t uScreenId,
+HRESULT VBoxSDLFB::init(uint32_t uScreenId,
                      bool fFullscreen, bool fResizable, bool fShowSDLConfig,
                      bool fKeepHostRes, uint32_t u32FixedWidth,
@@ -95,8 +109,4 @@
     int rc;
     LogFlow(("VBoxSDLFB::VBoxSDLFB\n"));
-
-#if defined (RT_OS_WINDOWS)
-    refcnt = 0;
-#endif
 
     mScreenId       = uScreenId;
@@ -140,4 +150,11 @@
     Assert(mScreen);
     mfInitialized = true;
+#ifdef RT_OS_WINDOWS
+    HRESULT hr = CoCreateFreeThreadedMarshaler(this, //GetControllingUnknown(),
+                                             &m_pUnkMarshaler.p);
+    Log(("CoCreateFreeThreadedMarshaler hr %08X\n", hr));
+#endif
+
+    return 0;
 }
 
Index: /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h	(revision 51676)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.h	(revision 51677)
@@ -42,34 +42,33 @@
 class VBoxSDLFBOverlay;
 
-class VBoxSDLFB :
+class ATL_NO_VTABLE VBoxSDLFB :
+    public CComObjectRootEx<CComMultiThreadModel>,
     VBOX_SCRIPTABLE_IMPL(IFramebuffer)
 {
 public:
-    VBoxSDLFB(uint32_t uScreenId,
-              bool fFullscreen = false, bool fResizable = true, bool fShowSDLConfig = false,
-              bool fKeepHostRes = false, uint32_t u32FixedWidth = ~(uint32_t)0,
-              uint32_t u32FixedHeight = ~(uint32_t)0, uint32_t u32FixedBPP = ~(uint32_t)0,
-              bool fUpdateImage = false);
-    virtual ~VBoxSDLFB();
+    VBoxSDLFB();
+    ~VBoxSDLFB();
+
+    HRESULT init(uint32_t uScreenId,
+                 bool fFullscreen, bool fResizable, bool fShowSDLConfig,
+                 bool fKeepHostRes, uint32_t u32FixedWidth,
+                 uint32_t u32FixedHeight, uint32_t u32FixedBPP,
+                 bool fUpdateImage);
 
     static bool init(bool fShowSDLConfig);
     static void uninit();
 
-#ifdef RT_OS_WINDOWS
-    STDMETHOD_(ULONG, AddRef)()
-    {
-        return ::InterlockedIncrement (&refcnt);
-    }
-    STDMETHOD_(ULONG, Release)()
-    {
-        long cnt = ::InterlockedDecrement (&refcnt);
-        if (cnt == 0)
-            delete this;
-        return cnt;
-    }
-#endif
-    VBOX_SCRIPTABLE_DISPATCH_IMPL(IFramebuffer)
-
-    NS_DECL_ISUPPORTS
+    DECLARE_NOT_AGGREGATABLE(VBoxSDLFB)
+
+    DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+    BEGIN_COM_MAP(VBoxSDLFB)
+        COM_INTERFACE_ENTRY(IFramebuffer)
+        COM_INTERFACE_ENTRY2(IDispatch,IFramebuffer)
+        COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
+    END_COM_MAP()
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
 
     STDMETHOD(COMGETTER(Width))(ULONG *width);
@@ -194,7 +193,5 @@
 
 #endif
-#ifdef RT_OS_WINDOWS
-    long refcnt;
-#endif
+
     SDL_Surface *mSurfVRAM;
 
@@ -207,4 +204,8 @@
     ComPtr<IDisplaySourceBitmap> mpPendingSourceBitmap;
     bool mfUpdates;
+
+#ifdef RT_OS_WINDOWS
+     CComPtr <IUnknown>   m_pUnkMarshaler;
+#endif
 };
 
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 51676)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 51677)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -207,5 +207,5 @@
 
 static ULONG       gcMonitors = 1;
-static VBoxSDLFB  *gpFramebuffer[64];
+static ComObjPtr<VBoxSDLFB> gpFramebuffer[64];
 static SDL_Cursor *gpDefaultCursor = NULL;
 #ifdef VBOXSDL_WITH_X11
@@ -602,4 +602,5 @@
     RTPrintf("Usage:\n"
              "  --startvm <uuid|name>    Virtual machine to start, either UUID or name\n"
+             "  --separate               Run a separate VM process or attach to a running VM\n"
              "  --hda <file>             Set temporary first hard disk to file\n"
              "  --fda <file>             Set temporary first floppy disk to file\n"
@@ -823,4 +824,5 @@
     Guid uuidVM;
     char *vmName = NULL;
+    bool fSeparate = false;
     DeviceType_T bootDevice = DeviceType_Null;
     uint32_t memorySize = 0;
@@ -976,4 +978,9 @@
             }
         }
+        else if (   !strcmp(argv[curArg], "--separate")
+                 || !strcmp(argv[curArg], "-separate"))
+        {
+            fSeparate = true;
+        }
         else if (   !strcmp(argv[curArg], "--comment")
                  || !strcmp(argv[curArg], "-comment"))
@@ -1482,5 +1489,67 @@
     }
 
-    rc = pMachine->LockMachine(pSession, LockType_VM);
+    if (fSeparate)
+    {
+        MachineState_T machineState = MachineState_Null; 
+        pMachine->COMGETTER(State)(&machineState);
+        if (   machineState == MachineState_Running
+            || machineState == MachineState_Teleporting
+            || machineState == MachineState_LiveSnapshotting
+            || machineState == MachineState_Paused
+            || machineState == MachineState_TeleportingPausedVM
+           )
+        {
+            RTPrintf("VM is already running.\n");
+        }
+        else
+        {
+            ComPtr<IProgress> progress;
+            rc = pMachine->LaunchVMProcess(pSession, Bstr("headless").raw(), NULL, progress.asOutParam());
+            if (SUCCEEDED(rc) && !progress.isNull())
+            {
+                RTPrintf("Waiting for VM to power on...\n");
+                rc = progress->WaitForCompletion(-1);
+                if (SUCCEEDED(rc))
+                {
+                    BOOL completed = true;
+                    rc = progress->COMGETTER(Completed)(&completed);
+                    if (SUCCEEDED(rc))
+                    {
+                        LONG iRc;
+                        rc = progress->COMGETTER(ResultCode)(&iRc);
+                        if (SUCCEEDED(rc))
+                        {
+                            if (FAILED(iRc))
+                            {
+                                ProgressErrorInfo info(progress);
+                                com::GluePrintErrorInfo(info);
+                            }
+                            else
+                            {
+                                RTPrintf("VM has been successfully started.\n");
+                                /* LaunchVMProcess obtains a shared lock on the machine.
+                                 * Unlock it here, because the lock will be obtained below
+                                 * in the common code path as for already running VM.
+                                 */
+                                pSession->UnlockMachine();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (FAILED(rc))
+        {
+            RTPrintf("Error: failed to power up VM! No error text available.\n");
+            goto leave;
+        }
+
+        rc = pMachine->LockMachine(pSession, LockType_Shared);
+    }
+    else
+    {
+        rc = pMachine->LockMachine(pSession, LockType_VM);
+    }
+
     if (FAILED(rc))
     {
@@ -1509,4 +1578,5 @@
         goto leave;
     }
+
     // get the VM console
     pSession->COMGETTER(Console)(gpConsole.asOutParam());
@@ -1857,8 +1927,8 @@
     {
         // create our SDL framebuffer instance
-        gpFramebuffer[i] = new VBoxSDLFB(i, fFullscreen, fResizable, fShowSDLConfig, false,
-                                         fixedWidth, fixedHeight, fixedBPP);
-
-        if (!gpFramebuffer[i])
+        gpFramebuffer[i].createObject();
+        rc = gpFramebuffer[i]->init(i, fFullscreen, fResizable, fShowSDLConfig, false,
+                                    fixedWidth, fixedHeight, fixedBPP, fSeparate);
+        if (FAILED(rc))
         {
             RTPrintf("Error: could not create framebuffer object!\n");
@@ -1944,6 +2014,7 @@
             goto leave;
         }
+        ULONG dummy;
         LONG xOrigin, yOrigin;
-        rc = gpDisplay->GetScreenResolution(i, NULL, NULL, NULL, &xOrigin, &yOrigin);
+        rc = gpDisplay->GetScreenResolution(i, &dummy, &dummy, &dummy, &xOrigin, &yOrigin);
         gpFramebuffer[i]->setOrigin(xOrigin, yOrigin);
     }
@@ -2130,14 +2201,17 @@
     SDL_Event event;
 
-    LogFlow(("Powering up the VM...\n"));
-    rc = gpConsole->PowerUp(gpProgress.asOutParam());
-    if (rc != S_OK)
-    {
-        com::ErrorInfo info(gpConsole, COM_IIDOF(IConsole));
-        if (info.isBasicAvailable())
-            PrintError("Failed to power up VM", info.getText().raw());
-        else
-            RTPrintf("Error: failed to power up VM! No error text available.\n");
-        goto leave;
+    if (!fSeparate)
+    {
+        LogFlow(("Powering up the VM...\n"));
+        rc = gpConsole->PowerUp(gpProgress.asOutParam());
+        if (rc != S_OK)
+        {
+            com::ErrorInfo info(gpConsole, COM_IIDOF(IConsole));
+            if (info.isBasicAvailable())
+                PrintError("Failed to power up VM", info.getText().raw());
+            else
+                RTPrintf("Error: failed to power up VM! No error text available.\n");
+            goto leave;
+        }
     }
 
@@ -2220,5 +2294,6 @@
                         gpFramebuffer[event.user.code]->notifyChange(event.user.code);
                         /* update xOrigin, yOrigin -> mouse */
-                        rc = gpDisplay->GetScreenResolution(event.user.code, NULL, NULL, NULL, &xOrigin, &yOrigin);
+                        ULONG dummy;
+                        rc = gpDisplay->GetScreenResolution(event.user.code, &dummy, &dummy, &dummy, &xOrigin, &yOrigin);
                         gpFramebuffer[event.user.code]->setOrigin(xOrigin, yOrigin);
                         break;
@@ -2306,4 +2381,16 @@
         RTPrintf("Error: could not get mouse object!\n");
         goto leave;
+    }
+
+    if (fSeparate && gpMouse)
+    {
+        LogFlow(("Fetching mouse caps\n"));
+
+        /* Fetch current mouse status, etc */
+        gpMouse->COMGETTER(AbsoluteSupported)(&gfAbsoluteMouseGuest);
+        gpMouse->COMGETTER(RelativeSupported)(&gfRelativeMouseGuest);
+        gpMouse->COMGETTER(NeedsHostCursor)(&gfGuestNeedsHostCursor);
+
+        HandleGuestCapsChanged();
     }
 
@@ -2702,5 +2789,6 @@
                 gpFramebuffer[event.user.code]->notifyChange(event.user.code);
                 /* update xOrigin, yOrigin -> mouse */
-                rc = gpDisplay->GetScreenResolution(event.user.code, NULL, NULL, NULL, &xOrigin, &yOrigin);
+                ULONG dummy;
+                rc = gpDisplay->GetScreenResolution(event.user.code, &dummy, &dummy, &dummy, &xOrigin, &yOrigin);
                 gpFramebuffer[event.user.code]->setOrigin(xOrigin, yOrigin);
                 break;
@@ -2808,36 +2896,39 @@
         machineState = MachineState_Aborted;
 
-    /*
-     * Turn off the VM if it's running
-     */
-    if (   gpConsole
-        && (   machineState == MachineState_Running
-            || machineState == MachineState_Teleporting
-            || machineState == MachineState_LiveSnapshotting
-            /** @todo power off paused VMs too? */
+    if (!fSeparate)
+    {
+        /*
+         * Turn off the VM if it's running
+         */
+        if (   gpConsole
+            && (   machineState == MachineState_Running
+                || machineState == MachineState_Teleporting
+                || machineState == MachineState_LiveSnapshotting
+                /** @todo power off paused VMs too? */
+               )
            )
-       )
-    do
-    {
-        pConsoleListener->getWrapped()->ignorePowerOffEvents(true);
-        ComPtr<IProgress> pProgress;
-        CHECK_ERROR_BREAK(gpConsole, PowerDown(pProgress.asOutParam()));
-        CHECK_ERROR_BREAK(pProgress, WaitForCompletion(-1));
-        BOOL completed;
-        CHECK_ERROR_BREAK(pProgress, COMGETTER(Completed)(&completed));
-        ASSERT(completed);
-        LONG hrc;
-        CHECK_ERROR_BREAK(pProgress, COMGETTER(ResultCode)(&hrc));
-        if (FAILED(hrc))
-        {
-            com::ErrorInfo info;
-            if (info.isFullAvailable())
-                PrintError("Failed to power down VM",
-                           info.getText().raw(), info.getComponent().raw());
-            else
-                RTPrintf("Failed to power down virtual machine! No error information available (rc = 0x%x).\n", hrc);
-            break;
-        }
-    } while (0);
+        do
+        {
+            pConsoleListener->getWrapped()->ignorePowerOffEvents(true);
+            ComPtr<IProgress> pProgress;
+            CHECK_ERROR_BREAK(gpConsole, PowerDown(pProgress.asOutParam()));
+            CHECK_ERROR_BREAK(pProgress, WaitForCompletion(-1));
+            BOOL completed;
+            CHECK_ERROR_BREAK(pProgress, COMGETTER(Completed)(&completed));
+            ASSERT(completed);
+            LONG hrc;
+            CHECK_ERROR_BREAK(pProgress, COMGETTER(ResultCode)(&hrc));
+            if (FAILED(hrc))
+            {
+                com::ErrorInfo info;
+                if (info.isFullAvailable())
+                    PrintError("Failed to power down VM",
+                               info.getText().raw(), info.getComponent().raw());
+                else
+                    RTPrintf("Failed to power down virtual machine! No error information available (rc = 0x%x).\n", hrc);
+                break;
+            }
+        } while (0);
+    }
 
     /* unregister Console listener */
@@ -2859,5 +2950,5 @@
     {
         rc = gpMachine->DiscardSettings();
-        AssertComRC(rc);
+        AssertMsg(SUCCEEDED(rc), ("DiscardSettings %Rhrc, machineState %d\n", rc, machineState));
     }
 
