Index: /trunk/include/VBox/log.h
===================================================================
--- /trunk/include/VBox/log.h	(revision 52920)
+++ /trunk/include/VBox/log.h	(revision 52921)
@@ -494,4 +494,6 @@
     /** Main group, IMouseCapabilityChangedEvent. */
     LOG_GROUP_MAIN_MOUSECAPABILITYCHANGEDEVENT,
+    /** Main group, IMousePointerShape. */
+    LOG_GROUP_MAIN_MOUSEPOINTERSHAPE,
     /** Main group, IMousePointerShapeChangedEvent. */
     LOG_GROUP_MAIN_MOUSEPOINTERSHAPECHANGEDEVENT,
@@ -990,4 +992,5 @@
     "MAIN_MOUSE",   \
     "MAIN_MOUSECAPABILITYCHANGEDEVENT", \
+    "MAIN_MOUSEPOINTERSHAPE", \
     "MAIN_MOUSEPOINTERSHAPECHANGEDEVENT", \
     "MAIN_NATENGINE", \
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 52920)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 52921)
@@ -15038,6 +15038,79 @@
 
   <interface
+    name="IMousePointerShape" extends="$unknown"
+    uuid="4609f3e1-839a-4edd-b57f-cc4584b39173"
+    wsmap="managed"
+    >
+    <desc>
+      The guest mouse pointer description.
+    </desc>
+
+    <attribute name="visible" type="boolean" readonly="yes">
+      <desc>
+        Flag whether the pointer is visible.
+      </desc>
+    </attribute>
+    <attribute name="alpha" type="boolean" readonly="yes">
+      <desc>
+        Flag whether the pointer has an alpha channel.
+      </desc>
+    </attribute>
+    <attribute name="hotX" type="unsigned long" readonly="yes">
+      <desc>
+        The pointer hot spot X coordinate.
+      </desc>
+    </attribute>
+    <attribute name="hotY" type="unsigned long" readonly="yes">
+      <desc>
+        The pointer hot spot Y coordinate.
+      </desc>
+    </attribute>
+    <attribute name="width" type="unsigned long" readonly="yes">
+      <desc>
+        Width of the pointer shape in pixels.
+      </desc>
+    </attribute>
+    <attribute name="height" type="unsigned long" readonly="yes">
+      <desc>
+        Height of the pointer shape in pixels.
+      </desc>
+    </attribute>
+    <attribute name="shape" type="octet" safearray="yes" readonly="yes">
+      <desc>
+        Shape bitmaps.
+
+        The @a shape buffer contains a 1bpp (bits per pixel) AND mask
+        followed by a 32bpp XOR (color) mask.
+
+        For pointers without alpha channel the XOR mask pixels are
+        32 bit values: (lsb)BGR0(msb). For pointers with alpha channel
+        the XOR mask consists of (lsb)BGRA(msb) 32 bit values.
+
+        An AND mask is provided for pointers with alpha channel, so if the
+        client does not support alpha, the pointer could be
+        displayed as a normal color pointer.
+
+        The AND mask is a 1bpp bitmap with byte aligned scanlines. The
+        size of the AND mask therefore is <tt>cbAnd = (width + 7) / 8 *
+          height</tt>. The padding bits at the end of each scanline are
+        undefined.
+
+        The XOR mask follows the AND mask on the next 4-byte aligned
+        offset: <tt>uint8_t *pu8Xor = pu8And + (cbAnd + 3) &amp; ~3</tt>.
+        Bytes in the gap between the AND and the XOR mask are undefined.
+        The XOR mask scanlines have no gap between them and the size of
+        the XOR mask is: <tt>cbXor = width * 4 * height</tt>.
+
+        <note>
+          If @a shape size is 0, then the shape is not known or did not change.
+          This can happen if only the pointer visibility is changed.
+        </note>
+      </desc>
+    </attribute>
+  </interface>
+
+  <interface
     name="IMouse" extends="$unknown"
-    uuid="ee770393-415f-4421-b2d5-28b73cacf86a"
+    uuid="4c3fa51c-7b9a-4ecf-97f0-d75a945bd26c"
     wsmap="managed"
     >
@@ -15098,4 +15171,10 @@
         </note>
         <see><link to="#putMouseEvent"/></see>
+      </desc>
+    </attribute>
+
+    <attribute name="pointerShape" type="IMousePointerShape" readonly="yes">
+      <desc>
+        The current mouse pointer used by the guest.
       </desc>
     </attribute>
Index: /trunk/src/VBox/Main/include/MouseImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MouseImpl.h	(revision 52920)
+++ /trunk/src/VBox/Main/include/MouseImpl.h	(revision 52921)
@@ -57,4 +57,8 @@
     }
 
+    void updateMousePointerShape(bool fVisible, bool fAlpha,
+                                 uint32_t hotX, uint32_t hotY,
+                                 uint32_t width, uint32_t height,
+                                 const uint8_t *pu8Shape, uint32_t cbShape);
 private:
 
@@ -64,4 +68,5 @@
     HRESULT getMultiTouchSupported(BOOL *aMultiTouchSupported);
     HRESULT getNeedsHostCursor(BOOL *aNeedsHostCursor);
+    HRESULT getPointerShape(ComPtr<IMousePointerShape> &aPointerShape);
     HRESULT getEventSource(ComPtr<IEventSource> &aEventSource);
 
@@ -123,4 +128,17 @@
     uint32_t mfLastButtons;
 
+    ComPtr<IMousePointerShape> mPointerShape;
+    struct
+    {
+        bool fVisible;
+        bool fAlpha;
+        uint32_t hotX;
+        uint32_t hotY;
+        uint32_t width;
+        uint32_t height;
+        uint8_t *pu8Shape;
+        uint32_t cbShape;
+    } mPointerData;
+
     const ComObjPtr<EventSource> mEventSource;
     VBoxEventDesc                mMouseEvent;
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 52920)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 52921)
@@ -6382,4 +6382,8 @@
     }
 #endif
+    com::SafeArray<BYTE> aShape(ComSafeArrayInArg(pShape));
+    if (!mMouse.isNull())
+       mMouse->updateMousePointerShape(fVisible, fAlpha, xHot, yHot, width, height,
+                                       aShape.raw(), aShape.size());
 
     fireMousePointerShapeChangedEvent(mEventSource, fVisible, fAlpha, xHot, yHot, width, height, ComSafeArrayInArg(pShape));
Index: /trunk/src/VBox/Main/src-client/MouseImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/MouseImpl.cpp	(revision 52920)
+++ /trunk/src/VBox/Main/src-client/MouseImpl.cpp	(revision 52921)
@@ -21,4 +21,5 @@
 #include "DisplayImpl.h"
 #include "VMMDev.h"
+#include "MousePointerShapeWrap.h"
 
 #include "AutoCaller.h"
@@ -29,4 +30,152 @@
 
 #include <iprt/asm.h>
+
+class ATL_NO_VTABLE MousePointerShape:
+    public MousePointerShapeWrap
+{
+public:
+
+    DECLARE_EMPTY_CTOR_DTOR(MousePointerShape)
+
+    HRESULT FinalConstruct();
+    void FinalRelease();
+
+    /* Public initializer/uninitializer for internal purposes only. */
+    HRESULT init(ComObjPtr<Mouse> pMouse,
+                 bool fVisible, bool fAlpha,
+                 uint32_t hotX, uint32_t hotY,
+                 uint32_t width, uint32_t height,
+                 const uint8_t *pu8Shape, uint32_t cbShape);
+    void uninit();
+
+private:
+    // wrapped IMousePointerShape properties
+    virtual HRESULT getVisible(BOOL *aVisible);
+    virtual HRESULT getAlpha(BOOL *aAlpha);
+    virtual HRESULT getHotX(ULONG *aHotX);
+    virtual HRESULT getHotY(ULONG *aHotY);
+    virtual HRESULT getWidth(ULONG *aWidth);
+    virtual HRESULT getHeight(ULONG *aHeight);
+    virtual HRESULT getShape(std::vector<BYTE> &aShape);
+
+    struct Data
+    {
+        ComObjPtr<Mouse> pMouse;
+        bool fVisible;
+        bool fAlpha;
+        uint32_t hotX;
+        uint32_t hotY;
+        uint32_t width;
+        uint32_t height;
+        std::vector<BYTE> shape;
+    };
+
+    Data m;
+};
+
+/*
+ * MousePointerShape implementation.
+ */
+DEFINE_EMPTY_CTOR_DTOR(MousePointerShape)
+
+HRESULT MousePointerShape::FinalConstruct()
+{
+    return BaseFinalConstruct();
+}
+
+void MousePointerShape::FinalRelease()
+{
+    uninit();
+
+    BaseFinalRelease();
+}
+
+HRESULT MousePointerShape::init(ComObjPtr<Mouse> pMouse,
+                                bool fVisible, bool fAlpha,
+                                uint32_t hotX, uint32_t hotY,
+                                uint32_t width, uint32_t height,
+                                const uint8_t *pu8Shape, uint32_t cbShape)
+{
+    LogFlowThisFunc(("v %d, a %d, h %d,%d, %dx%d, cb %d\n",
+                     fVisible, fAlpha, hotX, hotY, width, height, cbShape));
+
+    /* Enclose the state transition NotReady->InInit->Ready */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    m.pMouse = pMouse;
+    m.fVisible = fVisible;
+    m.fAlpha   = fAlpha;
+    m.hotX     = hotX;
+    m.hotY     = hotY;
+    m.width    = width;
+    m.height   = height;
+    m.shape.resize(cbShape);
+    if (cbShape)
+    {
+        memcpy(&m.shape.front(), pu8Shape, cbShape);
+    }
+
+    /* Confirm a successful initialization */
+    autoInitSpan.setSucceeded();
+
+    return S_OK;
+}
+
+void MousePointerShape::uninit()
+{
+    LogFlowThisFunc(("\n"));
+
+    /* Enclose the state transition Ready->InUninit->NotReady */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+
+    m.pMouse.setNull();
+}
+
+HRESULT MousePointerShape::getVisible(BOOL *aVisible)
+{
+    *aVisible = m.fVisible;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getAlpha(BOOL *aAlpha)
+{
+    *aAlpha = m.fAlpha;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getHotX(ULONG *aHotX)
+{
+    *aHotX = m.hotX;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getHotY(ULONG *aHotY)
+{
+    *aHotY = m.hotY;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getWidth(ULONG *aWidth)
+{
+    *aWidth = m.width;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getHeight(ULONG *aHeight)
+{
+    *aHeight = m.height;
+    return S_OK;
+}
+
+HRESULT MousePointerShape::getShape(std::vector<BYTE> &aShape)
+{
+    aShape.resize(m.shape.size());
+    memcpy(&aShape.front(), &m.shape.front(), aShape.size());
+    return S_OK;
+}
+
 
 /** @name Mouse device capabilities bitfield
@@ -78,4 +227,5 @@
 {
     RT_ZERO(mpDrv);
+    RT_ZERO(mPointerData);
     mcLastX = 0x8000;
     mcLastY = 0x8000;
@@ -144,4 +294,10 @@
     }
 
+    mPointerShape.setNull();
+
+    RTMemFree(mPointerData.pu8Shape);
+    mPointerData.pu8Shape = NULL;
+    mPointerData.cbShape = 0;
+
     mMouseEvent.uninit();
     unconst(mEventSource).setNull();
@@ -149,4 +305,32 @@
 }
 
+void Mouse::updateMousePointerShape(bool fVisible, bool fAlpha,
+                                    uint32_t hotX, uint32_t hotY,
+                                    uint32_t width, uint32_t height,
+                                    const uint8_t *pu8Shape, uint32_t cbShape)
+{
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    RTMemFree(mPointerData.pu8Shape);
+    mPointerData.pu8Shape = NULL;
+    mPointerData.cbShape = 0;
+
+    mPointerData.fVisible = fVisible;
+    mPointerData.fAlpha   = fAlpha;
+    mPointerData.hotX     = hotX;
+    mPointerData.hotY     = hotY;
+    mPointerData.width    = width;
+    mPointerData.height   = height;
+    if (cbShape)
+    {
+        mPointerData.pu8Shape = (uint8_t *)RTMemDup(pu8Shape, cbShape);
+        if (mPointerData.pu8Shape)
+        {
+            mPointerData.cbShape = cbShape;
+        }
+    }
+
+    mPointerShape.setNull();
+}
 
 // IMouse properties
@@ -222,4 +406,36 @@
     *aNeedsHostCursor = i_guestNeedsHostCursor();
     return S_OK;
+}
+
+HRESULT Mouse::getPointerShape(ComPtr<IMousePointerShape> &aPointerShape)
+{
+    HRESULT hr = S_OK;
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (mPointerShape.isNull())
+    {
+        ComObjPtr<MousePointerShape> obj;
+        hr = obj.createObject();
+        if (SUCCEEDED(hr))
+        {
+            hr = obj->init(this, mPointerData.fVisible, mPointerData.fAlpha,
+                           mPointerData.hotX, mPointerData.hotY,
+                           mPointerData.width, mPointerData.height,
+                           mPointerData.pu8Shape, mPointerData.cbShape);
+        }
+
+        if (SUCCEEDED(hr))
+        {
+            mPointerShape = obj;
+        }
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        aPointerShape = mPointerShape;
+    }
+
+    return hr;
 }
 
