Index: /trunk/include/VBox/com/EventQueue.h
===================================================================
--- /trunk/include/VBox/com/EventQueue.h	(revision 46648)
+++ /trunk/include/VBox/com/EventQueue.h	(revision 46649)
@@ -1,8 +1,9 @@
+/* $Id$ */
 /** @file
- * MS COM / XPCOM Abstraction Layer - Event and EventQueue class declaration.
+ * Event queue class declaration.
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -27,9 +28,8 @@
 #define ___VBox_com_EventQueue_h
 
-#ifndef VBOX_WITH_XPCOM
-# include <Windows.h>
-#else // VBOX_WITH_XPCOM
-# include <nsEventQueueUtils.h>
-#endif // VBOX_WITH_XPCOM
+#include <list>
+
+#include <iprt/asm.h>
+#include <iprt/critsect.h>
 
 #include <VBox/com/defs.h>
@@ -52,6 +52,19 @@
 public:
 
-    Event() {}
-    virtual ~Event() {};
+    Event(void) :
+        mRefCount(0) { }
+    virtual ~Event(void) { AssertMsg(!mRefCount,
+                                     ("Reference count of event=%p not 0 on destruction (is %RU32)\n",
+                                      this, mRefCount)); }
+public:
+
+    uint32_t AddRef(void) { return ASMAtomicIncU32(&mRefCount); }
+    void     Release(void)
+    {
+        Assert(mRefCount);
+        uint32_t cRefs = ASMAtomicDecU32(&mRefCount);
+        if (!cRefs)
+            delete this;
+    }
 
 protected:
@@ -63,23 +76,20 @@
      *  @return reserved, should be NULL.
      */
-    virtual void *handler() { return NULL; }
+    virtual void *handler(void) { return NULL; }
 
     friend class EventQueue;
+
+protected:
+
+    /** The event's reference count. */
+    uint32_t mRefCount;
 };
+
+typedef std::list< Event* >                 EventQueueList;
+typedef std::list< Event* >::iterator       EventQueueListIterator;
+typedef std::list< Event* >::const_iterator EventQueueListIteratorConst;
 
 /**
  *  Simple event queue.
- *
- *  When using XPCOM, this will map onto the default XPCOM queue for the thread.
- *  So, if a queue is created on the main thread, it automatically processes
- *  XPCOM/IPC events while waiting.
- *
- *  When using Windows, Darwin and OS/2, this will map onto the native thread
- *  queue/runloop.  So, windows messages and what not will be processed while
- *  waiting for events.
- *
- *  @note It is intentional that there is no way to retrieve arbitrary
- *  events and controlling their processing. There is no use case which
- *  warrants introducing the complexity of platform independent events.
  */
 class EventQueue
@@ -87,50 +97,25 @@
 public:
 
-    EventQueue();
-    ~EventQueue(); /** @todo r=andy Why not virtual? */
+    EventQueue(void);
+    virtual ~EventQueue(void);
+
+public:
 
     BOOL postEvent(Event *event);
     int processEventQueue(RTMSINTERVAL cMsTimeout);
     int interruptEventQueueProcessing();
-    int getSelectFD();
-    static int init();
-    static int uninit();
-    static EventQueue *getMainEventQueue();
-
-#ifdef VBOX_WITH_XPCOM
-    already_AddRefed<nsIEventQueue> getIEventQueue()
-    {
-        return mEventQ.get();
-    }
-#else
-    static int dispatchMessageOnWindows(MSG const *pMsg, int rc);
-#endif
 
 private:
-    static EventQueue *sMainQueue;
 
-#ifndef VBOX_WITH_XPCOM
-
-    /** The thread which the queue belongs to. */
-    DWORD mThreadId;
-    /** Duplicated thread handle for MsgWaitForMultipleObjects. */
-    HANDLE mhThread;
-
-#else // VBOX_WITH_XPCOM
-
-    /** Whether it was created (and thus needs destroying) or if a queue already
-     *  associated with the thread was used. */
-    bool mEQCreated;
-
-    /** Whether event processing should be interrupted. */
-    bool mInterrupted;
-
-    nsCOMPtr <nsIEventQueue> mEventQ;
-    nsCOMPtr <nsIEventQueueService> mEventQService;
-
-    static void *PR_CALLBACK plEventHandler(PLEvent *self);
-    static void PR_CALLBACK plEventDestructor(PLEvent *self);
-
-#endif // VBOX_WITH_XPCOM
+    /** Critical section for serializing access to this
+     *  event queue. */
+    RTCRITSECT         mCritSect;
+    /** Event semaphore for getting notified on new
+     *  events being handled. */
+    RTSEMEVENT         mSemEvent;
+    /** The actual event queue, implemented as a list. */
+    EventQueueList     mEvents;
+    /** Shutdown indicator. */
+    bool               mShutdown;
 };
 
Index: /trunk/include/VBox/com/NativeEventQueue.h
===================================================================
--- /trunk/include/VBox/com/NativeEventQueue.h	(revision 46649)
+++ /trunk/include/VBox/com/NativeEventQueue.h	(revision 46649)
@@ -0,0 +1,140 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Event and EventQueue class declaration
+ */
+
+/*
+ * Copyright (C) 2006-2013 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_EventQueue_h
+#define ___VBox_com_EventQueue_h
+
+#ifndef VBOX_WITH_XPCOM
+# include <Windows.h>
+#else // VBOX_WITH_XPCOM
+# include <nsEventQueueUtils.h>
+#endif // VBOX_WITH_XPCOM
+
+#include <VBox/com/defs.h>
+#include <VBox/com/assert.h>
+
+namespace com
+{
+
+class MainEventQueue;
+
+/**
+ *  Base class for all events. Intended to be subclassed to introduce new
+ *  events and handlers for them.
+ *
+ *  Subclasses usually reimplement virtual #handler() (that does nothing by
+ *  default) and add new data members describing the event.
+ */
+class NativeEvent
+{
+public:
+
+    NativeEvent() {}
+    virtual ~NativeEvent() {};
+
+protected:
+
+    /**
+     *  Event handler. Called in the context of the event queue's thread.
+     *  Always reimplemented by subclasses
+     *
+     *  @return reserved, should be NULL.
+     */
+    virtual void *handler() { return NULL; }
+
+    friend class NativeEventQueue;
+};
+
+/**
+ *  Simple event queue.
+ *
+ *  When using XPCOM, this will map onto the default XPCOM queue for the thread.
+ *  So, if a queue is created on the main thread, it automatically processes
+ *  XPCOM/IPC events while waiting.
+ *
+ *  When using Windows, Darwin and OS/2, this will map onto the native thread
+ *  queue/runloop.  So, windows messages and what not will be processed while
+ *  waiting for events.
+ *
+ *  @note It is intentional that there is no way to retrieve arbitrary
+ *  events and controlling their processing. There is no use case which
+ *  warrants introducing the complexity of platform independent events.
+ */
+class NativeEventQueue
+{
+public:
+
+    NativeEventQueue();
+    virtual ~NativeEventQueue();
+
+    BOOL postEvent(NativeEvent *event);
+    int processEventQueue(RTMSINTERVAL cMsTimeout);
+    int interruptEventQueueProcessing();
+    int getSelectFD();
+    static int init();
+    static int uninit();
+    static NativeEventQueue *getMainEventQueue();
+
+#ifdef VBOX_WITH_XPCOM
+    already_AddRefed<nsIEventQueue> getIEventQueue()
+    {
+        return mEventQ.get();
+    }
+#else
+    static int dispatchMessageOnWindows(MSG const *pMsg, int rc);
+#endif
+
+private:
+    static NativeEventQueue *sMainQueue;
+
+#ifndef VBOX_WITH_XPCOM
+
+    /** The thread which the queue belongs to. */
+    DWORD mThreadId;
+    /** Duplicated thread handle for MsgWaitForMultipleObjects. */
+    HANDLE mhThread;
+
+#else // VBOX_WITH_XPCOM
+
+    /** Whether it was created (and thus needs destroying) or if a queue already
+     *  associated with the thread was used. */
+    bool mEQCreated;
+
+    /** Whether event processing should be interrupted. */
+    bool mInterrupted;
+
+    nsCOMPtr <nsIEventQueue> mEventQ;
+    nsCOMPtr <nsIEventQueueService> mEventQService;
+
+    static void *PR_CALLBACK plEventHandler(PLEvent *self);
+    static void PR_CALLBACK plEventDestructor(PLEvent *self);
+
+#endif // VBOX_WITH_XPCOM
+};
+
+} /* namespace com */
+
+#endif
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-posix.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-posix.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-posix.cpp	(revision 46649)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -27,5 +27,5 @@
 #include <VBox/com/errorprint.h>
 
-#include <VBox/com/EventQueue.h>
+#include <VBox/com/NativeEventQueue.h>
 #include <VBox/com/listeners.h>
 #include <VBox/com/VirtualBox.h>
@@ -136,5 +136,5 @@
     Bstr bstrOperationDescription;
 
-    EventQueue::getMainEventQueue()->processEventQueue(0);
+    NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     ULONG cOperations = 1;
@@ -205,5 +205,5 @@
         progress->WaitForCompletion(100);
 
-        EventQueue::getMainEventQueue()->processEventQueue(0);
+        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
         hrc = progress->COMGETTER(Completed(&fCompleted));
     }
@@ -560,5 +560,5 @@
 
     autostartConfigAstDestroy(pCfgAst);
-    EventQueue::getMainEventQueue()->processEventQueue(0);
+    NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     autostartShutdown();
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp	(revision 46649)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -28,5 +28,5 @@
 #include <VBox/com/errorprint.h>
 
-#include <VBox/com/EventQueue.h>
+#include <VBox/com/NativeEventQueue.h>
 #include <VBox/com/listeners.h>
 #include <VBox/com/VirtualBox.h>
@@ -93,5 +93,5 @@
     Bstr bstrOperationDescription;
 
-    EventQueue::getMainEventQueue()->processEventQueue(0);
+    NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     ULONG cOperations = 1;
@@ -126,5 +126,5 @@
         progress->WaitForCompletion(100);
 
-        EventQueue::getMainEventQueue()->processEventQueue(0);
+        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
         hrc = progress->COMGETTER(Completed(&fCompleted));
     }
Index: /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 46649)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2011-2012 Oracle Corporation
+ * Copyright (C) 2011-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -28,5 +28,5 @@
 # include <VBox/com/errorprint.h>
 
-# include <VBox/com/EventQueue.h>
+# include <VBox/com/NativeEventQueue.h>
 # include <VBox/com/listeners.h>
 # include <VBox/com/VirtualBox.h>
@@ -132,5 +132,5 @@
 static ComPtr<IEventSource>      g_pEventSourceClient = NULL;
 static ComPtr<IEventListener>    g_pVBoxEventListener = NULL;
-static EventQueue               *g_pEventQ = NULL;
+static NativeEventQueue         *g_pEventQ = NULL;
 
 /* Prototypes. */
@@ -685,5 +685,5 @@
     {
         /* Initialize global weak references. */
-        g_pEventQ = com::EventQueue::getMainEventQueue();
+        g_pEventQ = com::NativeEventQueue::getMainEventQueue();
 
         /*
@@ -1148,5 +1148,5 @@
     RTEXITCODE rcExit = watchdogMain(&handlerArg);
 
-    EventQueue::getMainEventQueue()->processEventQueue(0);
+    NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     watchdogShutdown();
Index: /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 46649)
@@ -22,5 +22,5 @@
 #include <VBox/com/ErrorInfo.h>
 #include <VBox/com/errorprint.h>
-#include <VBox/com/EventQueue.h>
+#include <VBox/com/NativeEventQueue.h>
 
 #include <VBox/com/VirtualBox.h>
@@ -74,5 +74,5 @@
 /* global weak references (for event handlers) */
 static IConsole *gConsole = NULL;
-static EventQueue *gEventQ = NULL;
+static NativeEventQueue *gEventQ = NULL;
 
 /* flag whether frontend should terminate */
@@ -194,13 +194,15 @@
                     AssertComRC(hrc);
 
+                    Bstr strValue;
+                    hrc = pChangedEvent->COMGETTER(Value)(strValue.asOutParam());
+                    AssertComRC(hrc);
+
                     Utf8Str utf8Key = strKey;
-                    LogRelFlow(("Guest property \"%s\" has been changed\n", utf8Key.c_str()));
+                    Utf8Str utf8Value = strValue;
+                    LogRelFlow(("Guest property \"%s\" has been changed to \"%s\"\n",
+                                utf8Key.c_str(), utf8Value.c_str()));
 
                     if (utf8Key.equals("/VirtualBox/GuestInfo/OS/NoLoggedInUsers"))
                     {
-                        Bstr strValue;
-                        pChangedEvent->COMGETTER(Value)(strValue.asOutParam());
-                        Utf8Str utf8Value = strValue;
-
                         LogRelFlow(("Guest indicates that there %s logged in users\n",
                                     utf8Value.equals("true") ? "are no" : "are"));
@@ -1103,5 +1105,5 @@
         /* initialize global references */
         gConsole = console;
-        gEventQ = com::EventQueue::getMainEventQueue();
+        gEventQ = com::NativeEventQueue::getMainEventQueue();
 
         /* VirtualBoxClient events registration. */
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 46649)
@@ -27,5 +27,5 @@
 # include <VBox/com/ErrorInfo.h>
 # include <VBox/com/errorprint.h>
-# include <VBox/com/EventQueue.h>
+# include <VBox/com/NativeEventQueue.h>
 
 # include <VBox/com/VirtualBox.h>
@@ -91,5 +91,5 @@
     Bstr bstrOperationDescription;
 
-    EventQueue::getMainEventQueue()->processEventQueue(0);
+    NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     ULONG cOperations = 1;
@@ -199,5 +199,5 @@
         progress->WaitForCompletion(100);
 
-        EventQueue::getMainEventQueue()->processEventQueue(0);
+        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
         hrc = progress->COMGETTER(Completed(&fCompleted));
     }
@@ -585,5 +585,5 @@
         session->UnlockMachine();
 
-        EventQueue::getMainEventQueue()->processEventQueue(0);
+        NativeEventQueue::getMainEventQueue()->processEventQueue(0);
 
     // end "all-stuff" scope
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 46649)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -30,5 +30,5 @@
 #include <VBox/com/errorprint.h>
 #include <VBox/com/VirtualBox.h>
-#include <VBox/com/EventQueue.h>
+#include <VBox/com/NativeEventQueue.h>
 
 #include <VBox/err.h>
@@ -958,4 +958,11 @@
                 break;
 
+            /* Did we run out of time? */
+            if (   cMsTimeout
+                && RTTimeMilliTS() - u64StartMS > cMsTimeout)
+                break;
+
+            NativeEventQueue::getMainEventQueue()->processEventQueue(0);
+
         } /* while */
 
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 46648)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 46649)
@@ -28,5 +28,5 @@
 #include <VBox/com/errorprint.h>
 
-#include <VBox/com/EventQueue.h>
+#include <VBox/com/NativeEventQueue.h>
 #include <VBox/com/VirtualBox.h>
 
@@ -1378,5 +1378,5 @@
     ComPtr<ISession> pSession;
     bool sessionOpened = false;
-    EventQueue* eventQ = com::EventQueue::getMainEventQueue();
+    NativeEventQueue* eventQ = com::NativeEventQueue::getMainEventQueue();
 
     ComPtr<IMachine> pMachine;
Index: /trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Main/Makefile.kmk	(revision 46648)
+++ /trunk/src/VBox/Main/Makefile.kmk	(revision 46649)
@@ -736,4 +736,5 @@
 	glue/AutoLock.cpp \
 	glue/EventQueue.cpp \
+	glue/NativeEventQueue.cpp \
 	glue/ErrorInfo.cpp \
 	glue/errorprint.cpp
Index: /trunk/src/VBox/Main/glue/EventQueue.cpp
===================================================================
--- /trunk/src/VBox/Main/glue/EventQueue.cpp	(revision 46648)
+++ /trunk/src/VBox/Main/glue/EventQueue.cpp	(revision 46649)
@@ -1,10 +1,9 @@
 /* $Id$ */
 /** @file
- * MS COM / XPCOM Abstraction Layer:
- * Event and EventQueue class declaration
+ * Event queue class declaration.
  */
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -17,23 +16,16 @@
  */
 
+/** @todo Adapt / update documentation! */
+
 #include "VBox/com/EventQueue.h"
 
-#ifdef RT_OS_DARWIN
-# include <CoreFoundation/CFRunLoop.h>
-#endif
-
-#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
-# define USE_XPCOM_QUEUE
-#endif
-
+#include <iprt/asm.h>
 #include <new> /* For bad_alloc. */
 
 #include <iprt/err.h>
+#include <iprt/semaphore.h>
 #include <iprt/time.h>
 #include <iprt/thread.h>
 #include <iprt/log.h>
-#ifdef USE_XPCOM_QUEUE
-# include <errno.h>
-#endif
 
 namespace com
@@ -43,439 +35,29 @@
 ////////////////////////////////////////////////////////////////////////////////
 
-#ifndef VBOX_WITH_XPCOM
-
-# define CHECK_THREAD_RET(ret) \
-    do { \
-        AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \
-        if (GetCurrentThreadId() != mThreadId) \
-            return ret; \
-    } while (0)
-
-/** Magic LPARAM value for the WM_USER messages that we're posting.
- * @remarks This magic value is duplicated in
- *          vboxapi/PlatformMSCOM::interruptWaitEvents(). */
-#define EVENTQUEUE_WIN_LPARAM_MAGIC   UINT32_C(0xf241b819)
-
-
-#else // VBOX_WITH_XPCOM
-
-# define CHECK_THREAD_RET(ret) \
-    do { \
-        if (!mEventQ) \
-            return ret; \
-        BOOL isOnCurrentThread = FALSE; \
-        mEventQ->IsOnCurrentThread(&isOnCurrentThread); \
-        AssertMsg(isOnCurrentThread, ("Must be on event queue thread!")); \
-        if (!isOnCurrentThread) \
-            return ret; \
-    } while (0)
-
-#endif // VBOX_WITH_XPCOM
-
-/** Pointer to the main event queue. */
-EventQueue *EventQueue::sMainQueue = NULL;
-
-
-#ifdef VBOX_WITH_XPCOM
-
-struct MyPLEvent : public PLEvent
-{
-    MyPLEvent(Event *e) : event(e) {}
-    Event *event;
-};
-
-/* static */
-void *PR_CALLBACK com::EventQueue::plEventHandler(PLEvent *self)
-{
-    Event *ev = ((MyPLEvent *)self)->event;
-    if (ev)
-        ev->handler();
-    else
-    {
-        EventQueue *eq = (EventQueue *)self->owner;
-        Assert(eq);
-        eq->mInterrupted = true;
-    }
-    return NULL;
-}
-
-/* static */
-void PR_CALLBACK com::EventQueue::plEventDestructor(PLEvent *self)
-{
-    Event *ev = ((MyPLEvent *)self)->event;
-    if (ev)
-        delete ev;
-    delete self;
-}
-
-#endif // VBOX_WITH_XPCOM
-
-/**
- *  Constructs an event queue for the current thread.
- *
- *  Currently, there can be only one event queue per thread, so if an event
- *  queue for the current thread already exists, this object is simply attached
- *  to the existing event queue.
- */
-EventQueue::EventQueue()
-{
-    /** @todo r=andy This constructor does way too much. In case of failure
-     *               it's up to the caller to verify all sorts of stuff. Why
-     *               isn't this done in init() and moving the main queue
-     *               creation/deletion stuff to a dedicated function? */
-#ifndef VBOX_WITH_XPCOM
-
-    mThreadId = GetCurrentThreadId();
-    // force the system to create the message queue for the current thread
-    MSG msg;
-    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
-
-    if (!DuplicateHandle(GetCurrentProcess(),
-                         GetCurrentThread(),
-                         GetCurrentProcess(),
-                         &mhThread,
-                         0 /*dwDesiredAccess*/,
-                         FALSE /*bInheritHandle*/,
-                         DUPLICATE_SAME_ACCESS))
-      mhThread = INVALID_HANDLE_VALUE;
-
-#else // VBOX_WITH_XPCOM
-
-    mEQCreated = false;
-    mInterrupted = false;
-
-    // Here we reference the global nsIEventQueueService instance and hold it
-    // until we're destroyed. This is necessary to keep NS_ShutdownXPCOM() away
-    // from calling StopAcceptingEvents() on all event queues upon destruction of
-    // nsIEventQueueService, and makes sense when, for some reason, this happens
-    // *before* we're able to send a NULL event to stop our event handler thread
-    // when doing unexpected cleanup caused indirectly by NS_ShutdownXPCOM()
-    // that is performing a global cleanup of everything. A good example of such
-    // situation is when NS_ShutdownXPCOM() is called while the VirtualBox component
-    // is still alive (because it is still referenced): eventually, it results in
-    // a VirtualBox::uninit() call from where it is already not possible to post
-    // NULL to the event thread (because it stopped accepting events).
-
-    nsresult rc = NS_GetEventQueueService(getter_AddRefs(mEventQService));
-
-    if (NS_SUCCEEDED(rc))
-    {
-        rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
-                                                 getter_AddRefs(mEventQ));
-        if (rc == NS_ERROR_NOT_AVAILABLE)
-        {
-            rc = mEventQService->CreateThreadEventQueue();
-            if (NS_SUCCEEDED(rc))
-            {
-                mEQCreated = true;
-                rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
-                                                         getter_AddRefs(mEventQ));
-            }
-        }
-    }
-    AssertComRC(rc);
-
-#endif // VBOX_WITH_XPCOM
-}
-
-EventQueue::~EventQueue()
-{
-#ifndef VBOX_WITH_XPCOM
-    if (mhThread != INVALID_HANDLE_VALUE)
-    {
-        CloseHandle(mhThread);
-        mhThread = INVALID_HANDLE_VALUE;
-    }
-#else // VBOX_WITH_XPCOM
-    // process all pending events before destruction
-    if (mEventQ)
-    {
-        if (mEQCreated)
-        {
-            mEventQ->StopAcceptingEvents();
-            mEventQ->ProcessPendingEvents();
-            mEventQService->DestroyThreadEventQueue();
-        }
-        mEventQ = nsnull;
-        mEventQService = nsnull;
-    }
-#endif // VBOX_WITH_XPCOM
-}
-
-/**
- *  Initializes the main event queue instance.
- *  @returns VBox status code.
- *
- *  @remarks If you're using the rest of the COM/XPCOM glue library,
- *           com::Initialize() will take care of initializing and uninitializing
- *           the EventQueue class.  If you don't call com::Initialize, you must
- *           make sure to call this method on the same thread that did the
- *           XPCOM initialization or we'll end up using the wrong main queue.
- */
-/* static */
-int EventQueue::init()
-{
-    Assert(sMainQueue == NULL);
-    Assert(RTThreadIsMain(RTThreadSelf()));
-
-    try
-    {
-        sMainQueue = new EventQueue();
-
-#ifdef VBOX_WITH_XPCOM
-        /* Check that it actually is the main event queue, i.e. that
-           we're called on the right thread. */
-        nsCOMPtr<nsIEventQueue> q;
-        nsresult rv = NS_GetMainEventQ(getter_AddRefs(q));
-        Assert(NS_SUCCEEDED(rv));
-        Assert(q == sMainQueue->mEventQ);
-
-        /* Check that it's a native queue. */
-        PRBool fIsNative = PR_FALSE;
-        rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative);
-        Assert(NS_SUCCEEDED(rv) && fIsNative);
-#endif // VBOX_WITH_XPCOM
-    }
-    catch (std::bad_alloc &)
-    {
-        return VERR_NO_MEMORY;
-    }
-
-    return VINF_SUCCESS;
-}
-
-/**
- *  Uninitialize the global resources (i.e. the main event queue instance).
- *  @returns VINF_SUCCESS
- */
-/* static */
-int EventQueue::uninit()
-{
-    if (sMainQueue)
-    {
-        /* Must process all events to make sure that no NULL event is left
-         * after this point. It would need to modify the state of sMainQueue. */
-#ifdef RT_OS_DARWIN /* Do not process the native runloop, the toolkit may not be ready for it. */
-        sMainQueue->mEventQ->ProcessPendingEvents();
-#else
-        sMainQueue->processEventQueue(0);
-#endif
-        delete sMainQueue;
-        sMainQueue = NULL;
-    }
-    return VINF_SUCCESS;
-}
-
-/**
- *  Get main event queue instance.
- *
- *  Depends on init() being called first.
- */
-/* static */
-EventQueue* EventQueue::getMainEventQueue()
-{
-    return sMainQueue;
-}
-
-#ifdef VBOX_WITH_XPCOM
-# ifdef RT_OS_DARWIN
-/**
- * Wait for events and process them (Darwin).
- *
- * @retval  VINF_SUCCESS
- * @retval  VERR_TIMEOUT
- * @retval  VERR_INTERRUPTED
- *
- * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
- */
-static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout)
-{
-    /*
-     * Wait for the requested time, if we get a hit we do a poll to process
-     * any other pending messages.
-     *
-     * Note! About 1.0e10: According to the sources anything above 3.1556952e+9
-     *       means indefinite wait and 1.0e10 is what CFRunLoopRun() uses.
-     */
-    CFTimeInterval rdTimeout = cMsTimeout == RT_INDEFINITE_WAIT ? 1e10 : (double)cMsTimeout / 1000;
-    OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);
-    if (orc == kCFRunLoopRunHandledSource)
-    {
-        OSStatus orc2 = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);
-        if (   orc2 == kCFRunLoopRunStopped
-            || orc2 == kCFRunLoopRunFinished)
-            orc = orc2;
-    }
-    if (   orc == 0 /*???*/
-        || orc == kCFRunLoopRunHandledSource)
-        return VINF_SUCCESS;
-    if (   orc == kCFRunLoopRunStopped
-        || orc == kCFRunLoopRunFinished)
-        return VERR_INTERRUPTED;
-    AssertMsg(orc == kCFRunLoopRunTimedOut, ("Unexpected status code from CFRunLoopRunInMode: %#x", orc));
-    return VERR_TIMEOUT;
-}
-# else // !RT_OS_DARWIN
-
-/**
- * Wait for events (generic XPCOM).
- *
- * @retval  VINF_SUCCESS
- * @retval  VERR_TIMEOUT
- * @retval  VINF_INTERRUPTED
- * @retval  VERR_INTERNAL_ERROR_4
- *
- * @param   pQueue          The queue to wait on.
- * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
- */
-static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout)
-{
-    int     fd = pQueue->GetEventQueueSelectFD();
-    fd_set  fdsetR;
-    FD_ZERO(&fdsetR);
-    FD_SET(fd, &fdsetR);
-
-    fd_set  fdsetE = fdsetR;
-
-    struct timeval  tv = {0,0};
-    struct timeval *ptv;
-    if (cMsTimeout == RT_INDEFINITE_WAIT)
-        ptv = NULL;
-    else
-    {
-        tv.tv_sec  = cMsTimeout / 1000;
-        tv.tv_usec = (cMsTimeout % 1000) * 1000;
-        ptv = &tv;
-    }
-
-    int rc = select(fd + 1, &fdsetR, NULL, &fdsetE, ptv);
-    if (rc > 0)
-        rc = VINF_SUCCESS;
-    else if (rc == 0)
-        rc = VERR_TIMEOUT;
-    else if (errno == EINTR)
-        rc = VINF_INTERRUPTED;
-    else
-    {
-        static uint32_t s_ErrorCount = 0;
-        if (s_ErrorCount < 500)
-        {
-            LogRel(("waitForEventsOnXPCOM rc=%d errno=%d\n", rc, errno));
-            ++s_ErrorCount;
-        }
-
-        AssertMsgFailed(("rc=%d errno=%d\n", rc, errno));
-        rc = VERR_INTERNAL_ERROR_4;
-    }
-    return rc;
-}
-
-# endif // !RT_OS_DARWIN
-#endif // VBOX_WITH_XPCOM
-
-#ifndef VBOX_WITH_XPCOM
-
-/**
- * Dispatch a message on Windows.
- *
- * This will pick out our events and handle them specially.
- *
- * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg).
- * @param   pMsg    The message to dispatch.
- * @param   rc      The current status code.
- */
-/*static*/
-int EventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc)
-{
-    /*
-     * Check for and dispatch our events.
-     */
-    if (   pMsg->hwnd    == NULL
-        && pMsg->message == WM_USER)
-    {
-        if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC)
-        {
-            Event *pEvent = (Event *)pMsg->wParam;
-            if (pEvent)
-            {
-                pEvent->handler();
-                delete pEvent;
-            }
-            else
-                rc = VERR_INTERRUPTED;
-            return rc;
-        }
-        AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam));
-    }
-
-    /*
-     * Check for the quit message and dispatch the message the normal way.
-     */
-    if (pMsg->message == WM_QUIT)
-        rc = VERR_INTERRUPTED;
-    TranslateMessage(pMsg);
-    DispatchMessage(pMsg);
-
-    return rc;
-}
-
-
-/**
- * Process pending events (Windows).
- *
- * @retval  VINF_SUCCESS
- * @retval  VERR_TIMEOUT
- * @retval  VERR_INTERRUPTED.
- */
-static int processPendingEvents(void)
-{
-    int rc = VERR_TIMEOUT;
-    MSG Msg;
-    if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
-    {
-        rc = VINF_SUCCESS;
-        do
-            rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
-        while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE));
-    }
-    return rc;
-}
-
-#else // VBOX_WITH_XPCOM
-
-/**
- * Process pending XPCOM events.
- * @param pQueue The queue to process events on.
- * @retval  VINF_SUCCESS
- * @retval  VERR_TIMEOUT
- * @retval  VERR_INTERRUPTED (darwin only)
- * @retval  VERR_INTERNAL_ERROR_2
- */
-static int processPendingEvents(nsIEventQueue *pQueue)
-{
-    /* ProcessPendingEvents doesn't report back what it did, so check here. */
-    PRBool fHasEvents = PR_FALSE;
-    nsresult hr = pQueue->PendingEvents(&fHasEvents);
-    if (NS_FAILED(hr))
-        return VERR_INTERNAL_ERROR_2;
-
-    /* Process pending events. */
-    int rc = VINF_SUCCESS;
-    if (fHasEvents)
-        pQueue->ProcessPendingEvents();
-    else
-        rc = VERR_TIMEOUT;
-
-# ifdef RT_OS_DARWIN
-    /* Process pending native events. */
-    int rc2 = waitForEventsOnDarwin(0);
-    if (rc == VERR_TIMEOUT || rc2 == VERR_INTERRUPTED)
-        rc = rc2;
-# endif
-
-    return rc;
-}
-
-#endif // VBOX_WITH_XPCOM
+EventQueue::EventQueue(void)
+    : mShutdown(false)
+{
+    int rc = RTCritSectInit(&mCritSect);
+    AssertRC(rc);
+
+    rc = RTSemEventCreate(&mSemEvent);
+    AssertRC(rc);
+}
+
+EventQueue::~EventQueue(void)
+{
+    int rc = RTCritSectDelete(&mCritSect);
+    AssertRC(rc);
+
+    rc = RTSemEventDestroy(mSemEvent);
+    AssertRC(rc);
+
+    EventQueueListIterator it  = mEvents.begin();
+    while (it != mEvents.end())
+    {
+        (*it)->Release();
+        it = mEvents.erase(it);
+            }
+}
 
 /**
@@ -504,76 +86,56 @@
 int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
 {
-    int rc;
-    CHECK_THREAD_RET(VERR_INVALID_CONTEXT);
-
-#ifdef VBOX_WITH_XPCOM
-    /*
-     * Process pending events, if none are available and we're not in a
-     * poll call, wait for some to appear.  (We have to be a little bit
-     * careful after waiting for the events since Darwin will process
-     * them as part of the wait, while the XPCOM case will not.)
-     *
-     * Note! Unfortunately, WaitForEvent isn't interruptible with Ctrl-C,
-     *       while select() is.  So we cannot use it for indefinite waits.
-     */
-    rc = processPendingEvents(mEventQ);
-    if (    rc == VERR_TIMEOUT
-        &&  cMsTimeout > 0)
-    {
-# ifdef RT_OS_DARWIN
-        /** @todo check how Ctrl-C works on Darwin. */
-        rc = waitForEventsOnDarwin(cMsTimeout);
-        if (rc == VERR_TIMEOUT)
-            rc = processPendingEvents(mEventQ);
-# else // !RT_OS_DARWIN
-        rc = waitForEventsOnXPCOM(mEventQ, cMsTimeout);
-        if (    RT_SUCCESS(rc)
-            ||  rc == VERR_TIMEOUT)
-            rc = processPendingEvents(mEventQ);
-# endif // !RT_OS_DARWIN
-    }
-
-    if (  (   RT_SUCCESS(rc)
-           || rc == VERR_INTERRUPTED
-           || rc == VERR_TIMEOUT)
-        && mInterrupted)
-    {
-        mInterrupted = false;
-        rc = VERR_INTERRUPTED;
-    }
-
-#else // !VBOX_WITH_XPCOM
-    if (cMsTimeout == RT_INDEFINITE_WAIT)
-    {
-        BOOL fRet;
-        MSG  Msg;
-        rc = VINF_SUCCESS;
-        while (   rc != VERR_INTERRUPTED
-               && (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER))
-               && fRet != -1)
-            rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
-        if (fRet == 0)
-            rc = VERR_INTERRUPTED;
-        else if (fRet == -1)
-            rc = RTErrConvertFromWin32(GetLastError());
+    bool fWait;
+    int rc = RTCritSectEnter(&mCritSect);
+    if (RT_SUCCESS(rc))
+    {
+        fWait = mEvents.size() == 0;
+        if (!fWait)
+        {
+            int rc2 = RTCritSectLeave(&mCritSect);
+            AssertRC(rc2);
+    }
+    }
+
+    if (fWait)
+    {
+        int rc2 = RTCritSectLeave(&mCritSect);
+        AssertRC(rc2);
+
+        rc = RTSemEventWaitNoResume(mSemEvent, cMsTimeout);
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        if (ASMAtomicReadBool(&mShutdown))
+            return VERR_INTERRUPTED;
+
+        if (fWait)
+            rc = RTCritSectEnter(&mCritSect);
+        if (RT_SUCCESS(rc))
+        {
+            EventQueueListIterator it = mEvents.begin();
+            if (it != mEvents.end())
+            {
+                Event *pEvent = *it;
+                AssertPtr(pEvent);
+
+                mEvents.erase(it);
+
+                int rc2 = RTCritSectLeave(&mCritSect);
+                if (RT_SUCCESS(rc))
+                    rc = rc2;
+
+                pEvent->handler();
+                pEvent->Release();
     }
     else
     {
-        rc = processPendingEvents();
-        if (   rc == VERR_TIMEOUT
-            && cMsTimeout != 0)
-        {
-            DWORD rcW = MsgWaitForMultipleObjects(1,
-                                                  &mhThread,
-                                                  TRUE /*fWaitAll*/,
-                                                  cMsTimeout,
-                                                  QS_ALLINPUT);
-            AssertMsgReturn(rcW == WAIT_TIMEOUT || rcW == WAIT_OBJECT_0,
-                            ("%d\n", rcW),
-                            VERR_INTERNAL_ERROR_4);
-            rc = processPendingEvents();
-        }
-    }
-#endif // !VBOX_WITH_XPCOM
+                int rc2 = RTCritSectLeave(&mCritSect);
+                if (RT_SUCCESS(rc))
+                    rc = rc2;
+        }
+    }
+    }
 
     Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT);
@@ -588,11 +150,9 @@
  * @returns VBox status code.
  */
-int EventQueue::interruptEventQueueProcessing()
-{
-    /* Send a NULL event. This event will be picked up and handled specially
-     * both for XPCOM and Windows.  It is the responsibility of the caller to
-     * take care of not running the loop again in a way which will hang. */
-    postEvent(NULL);
-    return VINF_SUCCESS;
+int EventQueue::interruptEventQueueProcessing(void)
+{
+    ASMAtomicWriteBool(&mShutdown, true);
+
+    return RTSemEventSignal(mSemEvent);
 }
 
@@ -605,44 +165,48 @@
 BOOL EventQueue::postEvent(Event *pEvent)
 {
-#ifndef VBOX_WITH_XPCOM
-    /* Note! The event == NULL case is duplicated in vboxapi/PlatformMSCOM::interruptWaitEvents(). */
-    return PostThreadMessage(mThreadId, WM_USER, (WPARAM)pEvent, EVENTQUEUE_WIN_LPARAM_MAGIC);
-
-#else // VBOX_WITH_XPCOM
-
-    if (!mEventQ)
-        return FALSE;
-
-    try
-    {
-        MyPLEvent *pMyEvent = new MyPLEvent(pEvent);
-        mEventQ->InitEvent(pMyEvent, this, com::EventQueue::plEventHandler,
-                           com::EventQueue::plEventDestructor);
-        HRESULT rc = mEventQ->PostEvent(pMyEvent);
-        return NS_SUCCEEDED(rc);
-    }
-    catch (std::bad_alloc &ba)
-    {
-        AssertMsgFailed(("Out of memory while allocating memory for event=%p: %s\n",
-                         pEvent, ba.what()));
-    }
-
-    return FALSE;
-#endif // VBOX_WITH_XPCOM
-}
-
-
-/**
- *  Get select()'able selector for this event queue.
- *  This will return -1 on platforms and queue variants not supporting such
- *  functionality.
- */
-int EventQueue::getSelectFD()
-{
-#ifdef VBOX_WITH_XPCOM
-    return mEventQ->GetEventQueueSelectFD();
-#else
-    return -1;
-#endif
+    int rc = RTCritSectEnter(&mCritSect);
+    if (RT_SUCCESS(rc))
+    {
+       try
+        {
+            if (pEvent)
+            {
+                pEvent->AddRef();
+                mEvents.push_back(pEvent);
+            }
+            else /* No locking, since we're already in our crit sect. */
+                mShutdown = true;
+
+            size_t cEvents = mEvents.size();
+            if (cEvents > _1K) /** @todo Make value configurable? */
+            {
+                static int s_cBitchedAboutLotEvents = 0;
+                if (s_cBitchedAboutLotEvents < 10)
+                    LogRel(("Warning: Event queue received lots of events (%zu), expect delayed event handling (%d/10)\n",
+                            cEvents, ++s_cBitchedAboutLotEvents));
+            }
+
+            /* Leave critical section before signalling event. */
+            rc = RTCritSectLeave(&mCritSect);
+            if (RT_SUCCESS(rc))
+            {
+                int rc2 = RTSemEventSignal(mSemEvent);
+                AssertRC(rc2);
+            }
+        }
+        catch (std::bad_alloc &ba)
+        {
+            NOREF(ba);
+            rc = VERR_NO_MEMORY;
+        }
+
+        if (RT_FAILURE(rc))
+        {
+            int rc2 = RTCritSectLeave(&mCritSect);
+            AssertRC(rc2);
+        }
+    }
+
+    return RT_SUCCESS(rc) ? TRUE : FALSE;
 }
 
Index: /trunk/src/VBox/Main/glue/NativeEventQueue.cpp
===================================================================
--- /trunk/src/VBox/Main/glue/NativeEventQueue.cpp	(revision 46649)
+++ /trunk/src/VBox/Main/glue/NativeEventQueue.cpp	(revision 46649)
@@ -0,0 +1,655 @@
+/* $Id$ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Main event queue class declaration
+ */
+
+/*
+ * Copyright (C) 2006-2010 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 "VBox/com/NativeEventQueue.h"
+
+#include <new> /* For bad_alloc. */
+
+#ifdef RT_OS_DARWIN
+# include <CoreFoundation/CFRunLoop.h>
+#endif
+
+#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
+# define USE_XPCOM_QUEUE
+#endif
+
+#include <iprt/err.h>
+#include <iprt/time.h>
+#include <iprt/thread.h>
+#include <iprt/log.h>
+#ifdef USE_XPCOM_QUEUE
+# include <errno.h>
+#endif
+
+namespace com
+{
+
+// NativeEventQueue class
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef VBOX_WITH_XPCOM
+
+# define CHECK_THREAD_RET(ret) \
+    do { \
+        AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \
+        if (GetCurrentThreadId() != mThreadId) \
+            return ret; \
+    } while (0)
+
+/** Magic LPARAM value for the WM_USER messages that we're posting.
+ * @remarks This magic value is duplicated in
+ *          vboxapi/PlatformMSCOM::interruptWaitEvents(). */
+#define EVENTQUEUE_WIN_LPARAM_MAGIC   UINT32_C(0xf241b819)
+
+
+#else // VBOX_WITH_XPCOM
+
+# define CHECK_THREAD_RET(ret) \
+    do { \
+        if (!mEventQ) \
+            return ret; \
+        BOOL isOnCurrentThread = FALSE; \
+        mEventQ->IsOnCurrentThread(&isOnCurrentThread); \
+        AssertMsg(isOnCurrentThread, ("Must be on event queue thread!")); \
+        if (!isOnCurrentThread) \
+            return ret; \
+    } while (0)
+
+#endif // VBOX_WITH_XPCOM
+
+/** Pointer to the main event queue. */
+NativeEventQueue *NativeEventQueue::sMainQueue = NULL;
+
+
+#ifdef VBOX_WITH_XPCOM
+
+struct MyPLEvent : public PLEvent
+{
+    MyPLEvent(Event *e) : event(e) {}
+    Event *event;
+};
+
+/* static */
+void *PR_CALLBACK com::NativeEventQueue::plEventHandler(PLEvent *self)
+{
+    Event *ev = ((MyPLEvent *)self)->event;
+    if (ev)
+        ev->handler();
+    else
+    {
+        NativeEventQueue *eq = (NativeEventQueue *)self->owner;
+        Assert(eq);
+        eq->mInterrupted = true;
+    }
+    return NULL;
+}
+
+/* static */
+void PR_CALLBACK com::NativeEventQueue::plEventDestructor(PLEvent *self)
+{
+    Event *ev = ((MyPLEvent *)self)->event;
+    if (ev)
+        delete ev;
+    delete self;
+}
+
+#endif // VBOX_WITH_XPCOM
+
+/**
+ *  Constructs an event queue for the current thread.
+ *
+ *  Currently, there can be only one event queue per thread, so if an event
+ *  queue for the current thread already exists, this object is simply attached
+ *  to the existing event queue.
+ */
+NativeEventQueue::NativeEventQueue()
+{
+#ifndef VBOX_WITH_XPCOM
+
+    mThreadId = GetCurrentThreadId();
+    // force the system to create the message queue for the current thread
+    MSG msg;
+    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+
+    if (!DuplicateHandle(GetCurrentProcess(),
+                         GetCurrentThread(),
+                         GetCurrentProcess(),
+                         &mhThread,
+                         0 /*dwDesiredAccess*/,
+                         FALSE /*bInheritHandle*/,
+                         DUPLICATE_SAME_ACCESS))
+      mhThread = INVALID_HANDLE_VALUE;
+
+#else // VBOX_WITH_XPCOM
+
+    mEQCreated = false;
+    mInterrupted = false;
+
+    // Here we reference the global nsIEventQueueService instance and hold it
+    // until we're destroyed. This is necessary to keep NS_ShutdownXPCOM() away
+    // from calling StopAcceptingEvents() on all event queues upon destruction of
+    // nsIEventQueueService, and makes sense when, for some reason, this happens
+    // *before* we're able to send a NULL event to stop our event handler thread
+    // when doing unexpected cleanup caused indirectly by NS_ShutdownXPCOM()
+    // that is performing a global cleanup of everything. A good example of such
+    // situation is when NS_ShutdownXPCOM() is called while the VirtualBox component
+    // is still alive (because it is still referenced): eventually, it results in
+    // a VirtualBox::uninit() call from where it is already not possible to post
+    // NULL to the event thread (because it stopped accepting events).
+
+    nsresult rc = NS_GetEventQueueService(getter_AddRefs(mEventQService));
+
+    if (NS_SUCCEEDED(rc))
+    {
+        rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
+                                                 getter_AddRefs(mEventQ));
+        if (rc == NS_ERROR_NOT_AVAILABLE)
+        {
+            rc = mEventQService->CreateThreadEventQueue();
+            if (NS_SUCCEEDED(rc))
+            {
+                mEQCreated = true;
+                rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
+                                                         getter_AddRefs(mEventQ));
+            }
+        }
+    }
+    AssertComRC(rc);
+
+#endif // VBOX_WITH_XPCOM
+}
+
+NativeEventQueue::~NativeEventQueue()
+{
+#ifndef VBOX_WITH_XPCOM
+    if (mhThread != INVALID_HANDLE_VALUE)
+    {
+        CloseHandle(mhThread);
+        mhThread = INVALID_HANDLE_VALUE;
+    }
+#else // VBOX_WITH_XPCOM
+    // process all pending events before destruction
+    if (mEventQ)
+    {
+        if (mEQCreated)
+        {
+            mEventQ->StopAcceptingEvents();
+            mEventQ->ProcessPendingEvents();
+            mEventQService->DestroyThreadEventQueue();
+        }
+        mEventQ = nsnull;
+        mEventQService = nsnull;
+    }
+#endif // VBOX_WITH_XPCOM
+}
+
+/**
+ *  Initializes the main event queue instance.
+ *  @returns VBox status code.
+ *
+ *  @remarks If you're using the rest of the COM/XPCOM glue library,
+ *           com::Initialize() will take care of initializing and uninitializing
+ *           the NativeEventQueue class.  If you don't call com::Initialize, you must
+ *           make sure to call this method on the same thread that did the
+ *           XPCOM initialization or we'll end up using the wrong main queue.
+ */
+/* static */
+int NativeEventQueue::init()
+{
+    Assert(sMainQueue == NULL);
+    Assert(RTThreadIsMain(RTThreadSelf()));
+
+    try
+    {
+        sMainQueue = new NativeEventQueue();
+        AssertPtr(sMainQueue);
+#ifdef VBOX_WITH_XPCOM
+        /* Check that it actually is the main event queue, i.e. that
+           we're called on the right thread. */
+        nsCOMPtr<nsINativeEventQueue> q;
+        nsresult rv = NS_GetMainEventQ(getter_AddRefs(q));
+        Assert(NS_SUCCEEDED(rv));
+        Assert(q == sMainQueue->mEventQ);
+
+        /* Check that it's a native queue. */
+        PRBool fIsNative = PR_FALSE;
+        rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative);
+        Assert(NS_SUCCEEDED(rv) && fIsNative);
+#endif // VBOX_WITH_XPCOM
+    }
+    catch (std::bad_alloc &ba)
+    {
+        NOREF(ba);
+        return VERR_NO_MEMORY;
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ *  Uninitialize the global resources (i.e. the main event queue instance).
+ *  @returns VINF_SUCCESS
+ */
+/* static */
+int NativeEventQueue::uninit()
+{
+    if (sMainQueue)
+    {
+        /* Must process all events to make sure that no NULL event is left
+         * after this point. It would need to modify the state of sMainQueue. */
+#ifdef RT_OS_DARWIN /* Do not process the native runloop, the toolkit may not be ready for it. */
+        sMainQueue->mEventQ->ProcessPendingEvents();
+#else
+        sMainQueue->processEventQueue(0);
+#endif
+        delete sMainQueue;
+        sMainQueue = NULL;
+    }
+    return VINF_SUCCESS;
+}
+
+/**
+ *  Get main event queue instance.
+ *
+ *  Depends on init() being called first.
+ */
+/* static */
+NativeEventQueue* NativeEventQueue::getMainEventQueue()
+{
+    return sMainQueue;
+}
+
+#ifdef VBOX_WITH_XPCOM
+# ifdef RT_OS_DARWIN
+/**
+ * Wait for events and process them (Darwin).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TIMEOUT
+ * @retval  VERR_INTERRUPTED
+ *
+ * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
+ */
+static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout)
+{
+    /*
+     * Wait for the requested time, if we get a hit we do a poll to process
+     * any other pending messages.
+     *
+     * Note! About 1.0e10: According to the sources anything above 3.1556952e+9
+     *       means indefinite wait and 1.0e10 is what CFRunLoopRun() uses.
+     */
+    CFTimeInterval rdTimeout = cMsTimeout == RT_INDEFINITE_WAIT ? 1e10 : (double)cMsTimeout / 1000;
+    OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);
+    if (orc == kCFRunLoopRunHandledSource)
+    {
+        OSStatus orc2 = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);
+        if (   orc2 == kCFRunLoopRunStopped
+            || orc2 == kCFRunLoopRunFinished)
+            orc = orc2;
+    }
+    if (   orc == 0 /*???*/
+        || orc == kCFRunLoopRunHandledSource)
+        return VINF_SUCCESS;
+    if (   orc == kCFRunLoopRunStopped
+        || orc == kCFRunLoopRunFinished)
+        return VERR_INTERRUPTED;
+    AssertMsg(orc == kCFRunLoopRunTimedOut, ("Unexpected status code from CFRunLoopRunInMode: %#x", orc));
+    return VERR_TIMEOUT;
+}
+# else // !RT_OS_DARWIN
+
+/**
+ * Wait for events (generic XPCOM).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TIMEOUT
+ * @retval  VINF_INTERRUPTED
+ * @retval  VERR_INTERNAL_ERROR_4
+ *
+ * @param   pQueue          The queue to wait on.
+ * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
+ */
+static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout)
+{
+    int     fd = pQueue->GetEventQueueSelectFD();
+    fd_set  fdsetR;
+    FD_ZERO(&fdsetR);
+    FD_SET(fd, &fdsetR);
+
+    fd_set  fdsetE = fdsetR;
+
+    struct timeval  tv = {0,0};
+    struct timeval *ptv;
+    if (cMsTimeout == RT_INDEFINITE_WAIT)
+        ptv = NULL;
+    else
+    {
+        tv.tv_sec  = cMsTimeout / 1000;
+        tv.tv_usec = (cMsTimeout % 1000) * 1000;
+        ptv = &tv;
+    }
+
+    int rc = select(fd + 1, &fdsetR, NULL, &fdsetE, ptv);
+    if (rc > 0)
+        rc = VINF_SUCCESS;
+    else if (rc == 0)
+        rc = VERR_TIMEOUT;
+    else if (errno == EINTR)
+        rc = VINF_INTERRUPTED;
+    else
+    {
+        static uint32_t s_ErrorCount = 0;
+        if (s_ErrorCount < 500)
+        {
+            LogRel(("waitForEventsOnXPCOM rc=%d errno=%d\n", rc, errno));
+            ++s_ErrorCount;
+        }
+
+        AssertMsgFailed(("rc=%d errno=%d\n", rc, errno));
+        rc = VERR_INTERNAL_ERROR_4;
+    }
+    return rc;
+}
+
+# endif // !RT_OS_DARWIN
+#endif // VBOX_WITH_XPCOM
+
+#ifndef VBOX_WITH_XPCOM
+
+/**
+ * Dispatch a message on Windows.
+ *
+ * This will pick out our events and handle them specially.
+ *
+ * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg).
+ * @param   pMsg    The message to dispatch.
+ * @param   rc      The current status code.
+ */
+/*static*/
+int NativeEventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc)
+{
+    /*
+     * Check for and dispatch our events.
+     */
+    if (   pMsg->hwnd    == NULL
+        && pMsg->message == WM_USER)
+    {
+        if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC)
+        {
+            NativeEvent *pEvent = (NativeEvent *)pMsg->wParam;
+            if (pEvent)
+            {
+                pEvent->handler();
+                delete pEvent;
+            }
+            else
+                rc = VERR_INTERRUPTED;
+            return rc;
+        }
+        AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam));
+    }
+
+    /*
+     * Check for the quit message and dispatch the message the normal way.
+     */
+    if (pMsg->message == WM_QUIT)
+        rc = VERR_INTERRUPTED;
+    TranslateMessage(pMsg);
+    DispatchMessage(pMsg);
+
+    return rc;
+}
+
+
+/**
+ * Process pending events (Windows).
+ *
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TIMEOUT
+ * @retval  VERR_INTERRUPTED.
+ */
+static int processPendingEvents(void)
+{
+    int rc = VERR_TIMEOUT;
+    MSG Msg;
+    if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
+    {
+        rc = VINF_SUCCESS;
+        do
+            rc = NativeEventQueue::dispatchMessageOnWindows(&Msg, rc);
+        while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE));
+    }
+    return rc;
+}
+
+#else // VBOX_WITH_XPCOM
+
+/**
+ * Process pending XPCOM events.
+ * @param pQueue The queue to process events on.
+ * @retval  VINF_SUCCESS
+ * @retval  VERR_TIMEOUT
+ * @retval  VERR_INTERRUPTED (darwin only)
+ * @retval  VERR_INTERNAL_ERROR_2
+ */
+static int processPendingEvents(nsIEventQueue *pQueue)
+{
+    /* ProcessPendingEvents doesn't report back what it did, so check here. */
+    PRBool fHasEvents = PR_FALSE;
+    nsresult hr = pQueue->PendingEvents(&fHasEvents);
+    if (NS_FAILED(hr))
+        return VERR_INTERNAL_ERROR_2;
+
+    /* Process pending events. */
+    int rc = VINF_SUCCESS;
+    if (fHasEvents)
+        pQueue->ProcessPendingEvents();
+    else
+        rc = VERR_TIMEOUT;
+
+# ifdef RT_OS_DARWIN
+    /* Process pending native events. */
+    int rc2 = waitForEventsOnDarwin(0);
+    if (rc == VERR_TIMEOUT || rc2 == VERR_INTERRUPTED)
+        rc = rc2;
+# endif
+
+    return rc;
+}
+
+#endif // VBOX_WITH_XPCOM
+
+/**
+ * Process events pending on this event queue, and wait up to given timeout, if
+ * nothing is available.
+ *
+ * Must be called on same thread this event queue was created on.
+ *
+ * @param   cMsTimeout  The timeout specified as milliseconds.  Use
+ *                      RT_INDEFINITE_WAIT to wait till an event is posted on the
+ *                      queue.
+ *
+ * @returns VBox status code
+ * @retval  VINF_SUCCESS if one or more messages was processed.
+ * @retval  VERR_TIMEOUT if cMsTimeout expired.
+ * @retval  VERR_INVALID_CONTEXT if called on the wrong thread.
+ * @retval  VERR_INTERRUPTED if interruptEventQueueProcessing was called.
+ *          On Windows will also be returned when WM_QUIT is encountered.
+ *          On Darwin this may also be returned when the native queue is
+ *          stopped or destroyed/finished.
+ * @retval  VINF_INTERRUPTED if the native system call was interrupted by a
+ *          an asynchronous event delivery (signal) or just felt like returning
+ *          out of bounds.  On darwin it will also be returned if the queue is
+ *          stopped.
+ */
+int NativeEventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
+{
+    int rc;
+    CHECK_THREAD_RET(VERR_INVALID_CONTEXT);
+
+#ifdef VBOX_WITH_XPCOM
+    /*
+     * Process pending events, if none are available and we're not in a
+     * poll call, wait for some to appear.  (We have to be a little bit
+     * careful after waiting for the events since Darwin will process
+     * them as part of the wait, while the XPCOM case will not.)
+     *
+     * Note! Unfortunately, WaitForEvent isn't interruptible with Ctrl-C,
+     *       while select() is.  So we cannot use it for indefinite waits.
+     */
+    rc = processPendingEvents(mEventQ);
+    if (    rc == VERR_TIMEOUT
+        &&  cMsTimeout > 0)
+    {
+# ifdef RT_OS_DARWIN
+        /** @todo check how Ctrl-C works on Darwin. */
+        rc = waitForEventsOnDarwin(cMsTimeout);
+        if (rc == VERR_TIMEOUT)
+            rc = processPendingEvents(mEventQ);
+# else // !RT_OS_DARWIN
+        rc = waitForEventsOnXPCOM(mEventQ, cMsTimeout);
+        if (    RT_SUCCESS(rc)
+            ||  rc == VERR_TIMEOUT)
+            rc = processPendingEvents(mEventQ);
+# endif // !RT_OS_DARWIN
+    }
+
+    if (  (   RT_SUCCESS(rc)
+           || rc == VERR_INTERRUPTED
+           || rc == VERR_TIMEOUT)
+        && mInterrupted)
+    {
+        mInterrupted = false;
+        rc = VERR_INTERRUPTED;
+    }
+
+#else // !VBOX_WITH_XPCOM
+    if (cMsTimeout == RT_INDEFINITE_WAIT)
+    {
+        BOOL fRet;
+        MSG  Msg;
+        rc = VINF_SUCCESS;
+        while (   rc != VERR_INTERRUPTED
+               && (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER))
+               && fRet != -1)
+            rc = NativeEventQueue::dispatchMessageOnWindows(&Msg, rc);
+        if (fRet == 0)
+            rc = VERR_INTERRUPTED;
+        else if (fRet == -1)
+            rc = RTErrConvertFromWin32(GetLastError());
+    }
+    else
+    {
+        rc = processPendingEvents();
+        if (   rc == VERR_TIMEOUT
+            && cMsTimeout != 0)
+        {
+            DWORD rcW = MsgWaitForMultipleObjects(1,
+                                                  &mhThread,
+                                                  TRUE /*fWaitAll*/,
+                                                  cMsTimeout,
+                                                  QS_ALLINPUT);
+            AssertMsgReturn(rcW == WAIT_TIMEOUT || rcW == WAIT_OBJECT_0,
+                            ("%d\n", rcW),
+                            VERR_INTERNAL_ERROR_4);
+            rc = processPendingEvents();
+        }
+    }
+#endif // !VBOX_WITH_XPCOM
+
+    Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT);
+    return rc;
+}
+
+/**
+ * Interrupt thread waiting on event queue processing.
+ *
+ * Can be called on any thread.
+ *
+ * @returns VBox status code.
+ */
+int NativeEventQueue::interruptEventQueueProcessing()
+{
+    /* Send a NULL event. This event will be picked up and handled specially
+     * both for XPCOM and Windows.  It is the responsibility of the caller to
+     * take care of not running the loop again in a way which will hang. */
+    postEvent(NULL);
+    return VINF_SUCCESS;
+}
+
+/**
+ *  Posts an event to this event loop asynchronously.
+ *
+ *  @param  event   the event to post, must be allocated using |new|
+ *  @return         TRUE if successful and false otherwise
+ */
+BOOL NativeEventQueue::postEvent(NativeEvent *pEvent)
+{
+#ifndef VBOX_WITH_XPCOM
+    /* Note! The event == NULL case is duplicated in vboxapi/PlatformMSCOM::interruptWaitEvents(). */
+    BOOL fRc = PostThreadMessage(mThreadId, WM_USER, (WPARAM)pEvent, EVENTQUEUE_WIN_LPARAM_MAGIC);
+    if (!fRc)
+    {
+        static int s_cBitchedAboutFullNativeEventQueue = 0;
+        if (   GetLastError() == ERROR_NOT_ENOUGH_QUOTA
+            && s_cBitchedAboutFullNativeEventQueue < 10)
+            LogRel(("Warning: Asynchronous event queue (%p, thread %RI32) full, event (%p) not delivered (%d/10)\n",
+                    this, mThreadId, pEvent, ++s_cBitchedAboutFullNativeEventQueue));
+        else
+            AssertFailed();
+    }
+    return fRc;
+#else // VBOX_WITH_XPCOM
+    if (!mEventQ)
+        return FALSE;
+
+    try
+    {
+        MyPLEvent *pMyEvent = new MyPLEvent(pEvent);
+        mEventQ->InitEvent(pMyEvent, this, com::NativeEventQueue::plEventHandler,
+                           com::NativeEventQueue::plEventDestructor);
+        HRESULT rc = mEventQ->PostEvent(pMyEvent);
+        return NS_SUCCEEDED(rc);
+    }
+    catch (std::bad_alloc &ba)
+    {
+        AssertMsgFailed(("Out of memory while allocating memory for event=%p: %s\n",
+                         pEvent, ba.what()));
+    }
+
+    return FALSE;
+#endif // VBOX_WITH_XPCOM
+}
+
+/**
+ *  Get select()'able selector for this event queue.
+ *  This will return -1 on platforms and queue variants not supporting such
+ *  functionality.
+ */
+int NativeEventQueue::getSelectFD()
+{
+#ifdef VBOX_WITH_XPCOM
+    return mEventQ->GetNativeEventQueueSelectFD();
+#else
+    return -1;
+#endif
+}
+
+}
+/* namespace com */
Index: /trunk/src/VBox/Main/glue/initterm.cpp
===================================================================
--- /trunk/src/VBox/Main/glue/initterm.cpp	(revision 46648)
+++ /trunk/src/VBox/Main/glue/initterm.cpp	(revision 46649)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -49,5 +49,5 @@
 #include "VBox/com/com.h"
 #include "VBox/com/assert.h"
-#include "VBox/com/EventQueue.h"
+#include "VBox/com/NativeEventQueue.h"
 #include "VBox/com/AutoLock.h"
 
@@ -499,5 +499,5 @@
      */
     if (SUCCEEDED(rc))
-        EventQueue::init();
+        NativeEventQueue::init();
 
     return rc;
@@ -517,5 +517,5 @@
         if (-- gCOMMainInitCount == 0)
         {
-            EventQueue::uninit();
+            NativeEventQueue::uninit();
             ASMAtomicWriteHandle(&gCOMMainThread, NIL_RTTHREAD);
         }
@@ -556,5 +556,5 @@
             if (--gXPCOMInitCount == 0)
             {
-                EventQueue::uninit();
+                MainEventQueue::uninit();
                 rc = NS_ShutdownXPCOM(nsnull);
 
Index: /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 46648)
+++ /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 46649)
@@ -5356,32 +5356,43 @@
     AssertReturn(pvUser, VERR_INVALID_POINTER);
 
-    com::Initialize();
-
-    // create an event queue for the current thread
-    EventQueue *eventQ = new EventQueue();
-    AssertReturn(eventQ, VERR_NO_MEMORY);
-
-    // return the queue to the one who created this thread
-    *(static_cast <EventQueue **>(pvUser)) = eventQ;
-    // signal that we're ready
-    RTThreadUserSignal(thread);
-
-    /*
-     * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes
-     * we must not stop processing events and delete the "eventQ" object. This must
-     * be done ONLY when we stop this loop via interruptEventQueueProcessing().
-     * See @bugref{5724}.
-     */
-    while (eventQ->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED)
-        /* nothing */ ;
-
-    delete eventQ;
+    HRESULT hr = com::Initialize();
+    if (FAILED(hr))
+        return VERR_COM_UNEXPECTED;
+
+    int rc = VINF_SUCCESS;
+
+    try
+    {
+        /* Create an event queue for the current thread. */
+        EventQueue *pEventQueue = new EventQueue();
+        AssertPtr(pEventQueue);
+
+        /* Return the queue to the one who created this thread. */
+        *(static_cast <EventQueue **>(pvUser)) = pEventQueue;
+
+        /* signal that we're ready. */
+        RTThreadUserSignal(thread);
+
+        /*
+         * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes
+         * we must not stop processing events and delete the pEventQueue object. This must
+         * be done ONLY when we stop this loop via interruptEventQueueProcessing().
+         * See @bugref{5724}.
+         */
+        while (pEventQueue->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED)
+            /* nothing */ ;
+
+        delete pEventQueue;
+    }
+    catch (std::bad_alloc &ba)
+    {
+        rc = VERR_NO_MEMORY;
+        NOREF(ba);
+    }
 
     com::Shutdown();
 
-
-    LogFlowFuncLeave();
-
-    return 0;
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
Index: /trunk/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp	(revision 46648)
+++ /trunk/src/libs/xpcom18a4/java/src/nsJavaInterfaces.cpp	(revision 46649)
@@ -355,5 +355,5 @@
 
 #ifdef VBOX
-#  include <VBox/com/EventQueue.h>
+#  include <VBox/com/NativeEventQueue.h>
 #  include <iprt/err.h>
 
@@ -361,5 +361,5 @@
 XPCOM_NATIVE2(waitForEvents) (JNIEnv *env, jobject, jlong aTimeout)
 {
-    com::EventQueue* aEventQ = com::EventQueue::getMainEventQueue();
+    com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
     NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
     if (!aEventQ)
Index: /trunk/src/libs/xpcom18a4/java/src/nsThreadUtils.h
===================================================================
--- /trunk/src/libs/xpcom18a4/java/src/nsThreadUtils.h	(revision 46648)
+++ /trunk/src/libs/xpcom18a4/java/src/nsThreadUtils.h	(revision 46649)
@@ -51,9 +51,9 @@
 }
 
-#include "VBox/com/EventQueue.h"
+#include "VBox/com/NativeEventQueue.h"
 
 inline already_AddRefed<nsIEventQueue> do_GetMainThreadQueue()
 {
-  com::EventQueue* eq = com::EventQueue::getMainEventQueue();
+  com::NativeEventQueue* eq = com::NativeEventQueue::getMainEventQueue();
   NS_ASSERTION(eq != nsnull, "Must be valid");
   return eq->getIEventQueue();
Index: /trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
===================================================================
--- /trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp	(revision 46648)
+++ /trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp	(revision 46649)
@@ -511,5 +511,5 @@
 #ifdef VBOX
 
-#  include <VBox/com/EventQueue.h>
+#  include <VBox/com/NativeEventQueue.h>
 #  include <iprt/err.h>
 
@@ -522,5 +522,5 @@
 
     int rc;
-    com::EventQueue* aEventQ = com::EventQueue::getMainEventQueue();
+    com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
     NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
     if (!aEventQ)
@@ -557,5 +557,5 @@
 PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args)
 {
-  com::EventQueue* aEventQ = com::EventQueue::getMainEventQueue();
+  com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue();
   NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue");
   if (!aEventQ)
