Index: /trunk/include/VBox/VBoxGuest.h
===================================================================
--- /trunk/include/VBox/VBoxGuest.h	(revision 17195)
+++ /trunk/include/VBox/VBoxGuest.h	(revision 17196)
@@ -36,4 +36,5 @@
 # include <iprt/stdarg.h>
 #endif
+#include <iprt/assert.h>
 #include <VBox/err.h>
 #include <VBox/ostypes.h>
@@ -238,4 +239,5 @@
     uint32_t reserved2;
 } VMMDevRequestHeader;
+AssertCompileSize(VMMDevRequestHeader, 24);
 
 /** mouse status request structure */
@@ -640,4 +642,5 @@
     int32_t result;
 } VMMDevHGCMRequestHeader;
+AssertCompileSize(VMMDevHGCMRequestHeader, 24+8);
 
 /** HGCM service location types. */
@@ -1227,4 +1230,7 @@
     /** The user address of the data buffer. */
     RTR3PTR     pvDataR3;
+#if HC_ARCH_BITS == 32
+    uint32_t    u32Padding;
+#endif    
 } VBGLBIGREQ;
 /** Pointer to a request wrapper for solaris guests. */
@@ -1287,5 +1293,6 @@
 #endif /* RT_ARCH_AMD64 */
 
-/** IOCTL to VBoxGuest to query the VMMDev IO port region start. */
+/** IOCTL to VBoxGuest to query the VMMDev IO port region start. 
+ * @remarks Ring-0 only. */
 #define VBOXGUEST_IOCTL_GETVMMDEVPORT   VBOXGUEST_IOCTL_CODE(1, sizeof(VBoxGuestPortInfo))
 
@@ -1298,10 +1305,10 @@
 
 /** IOCTL to VBoxGuest to wait for a VMMDev host notification */
-#define VBOXGUEST_IOCTL_WAITEVENT       VBOXGUEST_IOCTL_CODE(2, sizeof(VBoxGuestWaitEventInfo))
+#define VBOXGUEST_IOCTL_WAITEVENT       VBOXGUEST_IOCTL_CODE_(2, sizeof(VBoxGuestWaitEventInfo))
 
 /** IOCTL to VBoxGuest to interrupt (cancel) any pending WAITEVENTs and return.
  * Handled inside the guest additions and not seen by the host at all.
  * @see VBOXGUEST_IOCTL_WAITEVENT */
-#define VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS       VBOXGUEST_IOCTL_CODE(5, 0)
+#define VBOXGUEST_IOCTL_CANCEL_ALL_WAITEVENTS       VBOXGUEST_IOCTL_CODE_(5, 0)
 
 /** @name Result codes for VBoxGuestWaitEventInfo::u32Result
@@ -1330,9 +1337,10 @@
     uint32_t u32EventFlagsOut;
 } VBoxGuestWaitEventInfo;
+AssertCompileSize(VBoxGuestWaitEventInfo, 16);
 
 /** IOCTL to VBoxGuest to perform a VMM request
  * @remark  The data buffer for this IOCtl has an variable size, keep this in mind
  *          on systems where this matters. */
-#define VBOXGUEST_IOCTL_VMMREQUEST(Size)            VBOXGUEST_IOCTL_CODE(3, (Size))
+#define VBOXGUEST_IOCTL_VMMREQUEST(Size)            VBOXGUEST_IOCTL_CODE_(3, (Size))
 
 /** Input and output buffer layout of the IOCTL_VBOXGUEST_CTL_FILTER_MASK. */
@@ -1342,14 +1350,15 @@
     uint32_t u32NotMask;
 } VBoxGuestFilterMaskInfo;
+AssertCompileSize(VBoxGuestFilterMaskInfo, 8);
 #pragma pack()
 
 /** IOCTL to VBoxGuest to control event filter mask. */
-#define VBOXGUEST_IOCTL_CTL_FILTER_MASK             VBOXGUEST_IOCTL_CODE(4, sizeof(VBoxGuestFilterMaskInfo))
+#define VBOXGUEST_IOCTL_CTL_FILTER_MASK             VBOXGUEST_IOCTL_CODE_(4, sizeof(VBoxGuestFilterMaskInfo))
 
 /** IOCTL to VBoxGuest to check memory ballooning. */
-#define VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK      VBOXGUEST_IOCTL_CODE(7, 100)
+#define VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK      VBOXGUEST_IOCTL_CODE_(7, 100)
 
 /** IOCTL to VBoxGuest to perform backdoor logging. */
-#define VBOXGUEST_IOCTL_LOG(Size)                   VBOXGUEST_IOCTL_CODE(6, (Size))
+#define VBOXGUEST_IOCTL_LOG(Size)                   VBOXGUEST_IOCTL_CODE_(6, (Size))
 
 
@@ -1365,4 +1374,5 @@
     uint32_t u32ClientID;     /**< OUT */
 } VBoxGuestHGCMConnectInfo;
+AssertCompileSize(VBoxGuestHGCMConnectInfo, 4+4+128+4);
 
 typedef struct _VBoxGuestHGCMDisconnectInfo
@@ -1371,4 +1381,5 @@
     uint32_t u32ClientID;     /**< IN */
 } VBoxGuestHGCMDisconnectInfo;
+AssertCompileSize(VBoxGuestHGCMDisconnectInfo, 8);
 
 typedef struct _VBoxGuestHGCMCallInfo
@@ -1380,4 +1391,5 @@
     /* Parameters follow in form HGCMFunctionParameter aParms[cParms] */
 } VBoxGuestHGCMCallInfo;
+AssertCompileSize(VBoxGuestHGCMCallInfo, 16);
 
 typedef struct _VBoxGuestHGCMCallInfoTimed
@@ -1389,4 +1401,5 @@
     /* Parameters follow in form HGCMFunctionParameter aParms[cParms] */
 } VBoxGuestHGCMCallInfoTimed;
+AssertCompileSize(VBoxGuestHGCMCallInfoTimed, 8+16);
 # pragma pack()
 
@@ -1395,11 +1408,12 @@
 # define VBOXGUEST_IOCTL_HGCM_CALL(Size)          VBOXGUEST_IOCTL_CODE(18, (Size))
 # define VBOXGUEST_IOCTL_HGCM_CALL_TIMED(Size)    VBOXGUEST_IOCTL_CODE(20, (Size))
-# define VBOXGUEST_IOCTL_CLIPBOARD_CONNECT        VBOXGUEST_IOCTL_CODE(19, sizeof(uint32_t))
-#ifdef RT_ARCH_AMD64
+# define VBOXGUEST_IOCTL_CLIPBOARD_CONNECT        VBOXGUEST_IOCTL_CODE_(19, sizeof(uint32_t))
+# ifdef RT_ARCH_AMD64
 /* Following HGCM IOCtls can be used by a 32 bit application on a 64 bit guest (Windows OpenGL guest driver). */
-# define VBOXGUEST_IOCTL_HGCM_CONNECT_32          VBOXGUEST_IOCTL_CODE_32(16, sizeof(VBoxGuestHGCMConnectInfo))
-# define VBOXGUEST_IOCTL_HGCM_DISCONNECT_32       VBOXGUEST_IOCTL_CODE_32(17, sizeof(VBoxGuestHGCMDisconnectInfo))
-# define VBOXGUEST_IOCTL_HGCM_CALL_32(Size)       VBOXGUEST_IOCTL_CODE_32(18, (Size))
-#endif /* RT_ARCH_AMD64 */
+#  define VBOXGUEST_IOCTL_HGCM_CONNECT_32         VBOXGUEST_IOCTL_CODE_32(16, sizeof(VBoxGuestHGCMConnectInfo))
+#  define VBOXGUEST_IOCTL_HGCM_DISCONNECT_32      VBOXGUEST_IOCTL_CODE_32(17, sizeof(VBoxGuestHGCMDisconnectInfo))
+#  define VBOXGUEST_IOCTL_HGCM_CALL_32(Size)      VBOXGUEST_IOCTL_CODE_32(18, (Size))
+#  define VBOXGUEST_IOCTL_HGCM_CALL_TIMED_32(Size) VBOXGUEST_IOCTL_CODE_32(20, (Size))
+# endif /* RT_ARCH_AMD64 */
 
 # define VBOXGUEST_HGCM_CALL_PARMS(a)       ((HGCMFunctionParameter *)((uint8_t *)(a) + sizeof (VBoxGuestHGCMCallInfo)))
Index: /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp	(revision 17195)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp	(revision 17196)
@@ -1112,4 +1112,71 @@
 
 
+#ifdef RT_ARCH_AMD64
+/** The 32-bit version HGCM call for 64-bit driver. */
+static int VBoxGuestCommonIOCtl_HGCMCall32(PVBOXGUESTDEVEXT pDevExt,
+                                           PVBOXGUESTSESSION pSession,
+                                           VBoxGuestHGCMCallInfo *pInfo,
+                                           uint32_t cMillies, bool fInterruptible,
+                                           size_t cbExtra, size_t cbData, size_t *pcbDataReturned)
+{
+    /*
+     * Some more validations.
+     */
+    if (pInfo->cParms > 4096) /* (Just make sure it doesn't overflow the next check.) */
+    {
+        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cParm=%RX32 is not sane\n", pInfo->cParms));
+        return VERR_INVALID_PARAMETER;
+    }
+    const size_t cbActual = cbExtra + sizeof(*pInfo) + pInfo->cParms * sizeof(HGCMFunctionParameter32);
+    if (cbData < cbActual)
+    {
+        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: cbData=%#zx (%zu) required size is %#zx (%zu)\n",
+             cbData, cbActual));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+     * Validate the client id.
+     */
+    const uint32_t u32ClientId = pInfo->u32ClientID;
+    unsigned i;
+    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
+    RTSpinlockAcquireNoInts(pDevExt->SessionSpinlock, &Tmp);
+    for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++)
+        if (pSession->aHGCMClientIds[i] == u32ClientId)
+            break;
+    RTSpinlockReleaseNoInts(pDevExt->SessionSpinlock, &Tmp);
+    if (RT_UNLIKELY(i >= RT_ELEMENTS(pSession->aHGCMClientIds)))
+    {
+        static unsigned s_cErrors = 0;
+        if (s_cErrors++ > 32)
+            LogRel(("VBoxGuestCommonIOCtl: HGCM_CALL: Invalid handle. u32Client=%RX32\n", u32ClientId));
+        return VERR_INVALID_HANDLE;
+    }
+
+    /*
+     * The VbglHGCMCall call will invoke the callback if the HGCM
+     * call is performed in an ASYNC fashion. This function can
+     * deal with cancelled requests, so we let user more requests
+     * be interruptible (should add a flag for this later I guess).
+     */
+    Log(("VBoxGuestCommonIOCtl: HGCM_CALL: u32Client=%RX32\n", pInfo->u32ClientID));
+    int rc;
+    if (fInterruptible)
+        rc = VbglHGCMCall32(pInfo, VBoxGuestHGCMAsyncWaitCallbackInterruptible, pDevExt, cMillies);
+    else
+        rc = VbglHGCMCall32(pInfo, VBoxGuestHGCMAsyncWaitCallback, pDevExt, cMillies);
+    if (RT_SUCCESS(rc))
+    {
+        Log(("VBoxGuestCommonIOCtl: HGCM_CALL: result=%Rrc\n", pInfo->result));
+        if (pcbDataReturned)
+            *pcbDataReturned = cbActual;
+    }
+    Log(("VBoxGuestCommonIOCtl: HGCM_CALL: Failed. rc=%Rrc.\n", rc));
+    return rc;
+}
+#endif
+
+
 /**
  * @returns VBox status code. Unlike the other HGCM IOCtls this will combine
@@ -1273,4 +1340,22 @@
                                            RT_OFFSETOF(VBoxGuestHGCMCallInfoTimed, info), cbData, pcbDataReturned);
     }
+# ifdef RT_ARCH_AMD64
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_32(0)))
+    {
+        CHECKRET_MIN_SIZE("HGCM_CALL", sizeof(VBoxGuestHGCMCallInfo));
+        bool fInterruptible = pSession->R0Process != NIL_RTR0PROCESS;
+        rc = VBoxGuestCommonIOCtl_HGCMCall32(pDevExt, pSession, (VBoxGuestHGCMCallInfo *)pvData, RT_INDEFINITE_WAIT,
+                                             fInterruptible,
+                                             0, cbData, pcbDataReturned);
+    }
+    else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_HGCM_CALL_TIMED_32(0)))
+    {
+        CHECKRET_MIN_SIZE("HGCM_CALL_TIMED", sizeof(VBoxGuestHGCMCallInfoTimed));
+        VBoxGuestHGCMCallInfoTimed *pInfo = (VBoxGuestHGCMCallInfoTimed *)pvData;
+        rc = VBoxGuestCommonIOCtl_HGCMCall32(pDevExt, pSession, &pInfo->info, pInfo->u32Timeout,
+                                             !!pInfo->fInterruptible || pSession->R0Process != NIL_RTR0PROCESS,
+                                             RT_OFFSETOF(VBoxGuestHGCMCallInfoTimed, info), cbData, pcbDataReturned);
+    }    
+# endif   
 #endif /* VBOX_WITH_HGCM */
     else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_LOG(0)))
@@ -1302,4 +1387,7 @@
 #ifdef VBOX_WITH_HGCM
             case VBOXGUEST_IOCTL_HGCM_CONNECT:
+# ifdef RT_ARCH_AMD64
+            case VBOXGUEST_IOCTL_HGCM_CONNECT_32:
+# endif              
                 CHECKRET_MIN_SIZE("HGCM_CONNECT", sizeof(VBoxGuestHGCMConnectInfo));
                 rc = VBoxGuestCommonIOCtl_HGCMConnect(pDevExt, pSession, (VBoxGuestHGCMConnectInfo *)pvData, pcbDataReturned);
@@ -1307,4 +1395,7 @@
 
             case VBOXGUEST_IOCTL_HGCM_DISCONNECT:
+# ifdef RT_ARCH_AMD64
+            case VBOXGUEST_IOCTL_HGCM_DISCONNECT_32:
+# endif              
                 CHECKRET_MIN_SIZE("HGCM_DISCONNECT", sizeof(VBoxGuestHGCMDisconnectInfo));
                 rc = VBoxGuestCommonIOCtl_HGCMDisconnect(pDevExt, pSession, (VBoxGuestHGCMDisconnectInfo *)pvData, pcbDataReturned);
@@ -1315,4 +1406,5 @@
                 rc = VBoxGuestCommonIOCtl_HGCMClipboardReConnect(pDevExt, (uint32_t *)pvData, pcbDataReturned);
                 break;
+                
 #endif /* VBOX_WITH_HGCM */
 
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3Lib.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3Lib.cpp	(revision 17195)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3Lib.cpp	(revision 17196)
@@ -337,4 +337,7 @@
     Hdr.cbData = cbData;
     Hdr.pvDataR3 = pvData;
+# if HC_ARCH_BITS == 32
+    Hdr.u32Padding = 0;
+# endif
 
 /** @todo test status code passing! */
