Index: /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris-streams.c
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris-streams.c	(revision 41019)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris-streams.c	(revision 41020)
@@ -549,14 +549,17 @@
 # define CBMSIOSRES (sizeof(g_TestResolution))
 
-static inline void testSetResolution(RTTEST hTest, queue_t *pWriteQueue,
+static inline bool testSetResolution(RTTEST hTest, queue_t *pWriteQueue,
                                      struct msgb *pMBlk)
 {
     PVBGR0STATE pState = (PVBGR0STATE)pWriteQueue->q_ptr;
-    RTTEST_CHECK_MSG(hTest,    pState->cMaxScreenX
-                            == g_TestResolution.width - 1,
-                     (hTest, "pState->cMaxScreenX=%d\n", pState->cMaxScreenX));
-    RTTEST_CHECK_MSG(hTest,    pState->cMaxScreenY
-                            == g_TestResolution.height - 1,
-                     (hTest, "pState->cMaxScreenY=%d\n", pState->cMaxScreenY));
+    RTTEST_CHECK_MSG_RET(hTest,    pState->cMaxScreenX
+                               == g_TestResolution.width - 1,
+                         (hTest, "pState->cMaxScreenX=%d\n",
+                          pState->cMaxScreenX), false);
+    RTTEST_CHECK_MSG_RET(hTest,    pState->cMaxScreenY
+                               == g_TestResolution.height - 1,
+                         (hTest, "pState->cMaxScreenY=%d\n",
+                          pState->cMaxScreenY), false);
+    return true;
 }
 
@@ -571,5 +574,5 @@
     size_t cbDataOut;
     int rcExp;
-    void (*pfnExtra)(RTTEST hTest, queue_t *pWriteQueue, struct msgb *pMBlk);
+    bool (*pfnExtra)(RTTEST hTest, queue_t *pWriteQueue, struct msgb *pMBlk);
     bool fCanTransparent;
 } g_asTestWPut[] =
@@ -599,4 +602,5 @@
 static void testWPutStreams(RTTEST hTest, unsigned i);
 static void testWPutTransparent(RTTEST hTest, unsigned i);
+static void testWPutIOCDataIn(RTTEST hTest, unsigned i);
 
 /** Test WPut's handling of different IOCtls, which is bulk of the logic in
@@ -609,9 +613,16 @@
     for (i = 0; i < RT_ELEMENTS(g_asTestWPut); ++i)
     {
+        AssertReturnVoid(g_asTestWPut[i].cbDataIn <= g_asTestWPut[i].cbData);
+        AssertReturnVoid(g_asTestWPut[i].cbDataOut <= g_asTestWPut[i].cbData);
         testWPutStreams(hTest, i);
         if (g_asTestWPut[i].fCanTransparent)
             testWPutTransparent(hTest, i);
-    }
-}
+        if (g_asTestWPut[i].fCanTransparent && g_asTestWPut[i].cbDataIn)
+            testWPutIOCDataIn(hTest, i);
+    }
+}
+
+
+#define MSG_DATA_SIZE 1024
 
 /** Simulate sending a streams IOCtl to WPut with the parameters from table
@@ -621,10 +632,11 @@
     queue_t aQueues[2];
     dev_t device = 0;
-    struct msgb MBlk, MBlkCont;
-    struct datab DBlk;
-    struct iocblk IOCBlk;
+    struct msgb *pMBlk = allocb(sizeof(struct iocblk), BPRI_MED);
+    struct msgb *pMBlkCont = allocb(MSG_DATA_SIZE, BPRI_MED);
+    struct iocblk *pIOCBlk = pMBlk ? (struct iocblk *)pMBlk->b_rptr : NULL;
     int rc, cFormat = 0;
-    unsigned char acData[1024];
-
+
+    AssertReturnVoid(pMBlk);
+    AssertReturnVoidStmt(pMBlkCont, freemsg(pMBlk));
     RT_ZERO(aQueues);
     doInitQueues(&aQueues[0]);
@@ -633,42 +645,37 @@
     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
                             == WR(&aQueues[0]), (hTest, "i=%u\n", i));
-    RT_ZERO(MBlk);
-    RT_ZERO(DBlk);
-    RT_ZERO(IOCBlk);
-    RT_ZERO(MBlkCont);
-    RT_ZERO(acData);
-    DBlk.db_type = M_IOCTL;
-    IOCBlk.ioc_cmd = g_asTestWPut[i].iIOCCmd;
-    IOCBlk.ioc_count = g_asTestWPut[i].cbData;
-    AssertReturnVoid(g_asTestWPut[i].cbData <= sizeof(acData));
-    AssertReturnVoid(g_asTestWPut[i].cbDataIn <= g_asTestWPut[i].cbData);
-    AssertReturnVoid(g_asTestWPut[i].cbDataOut <= g_asTestWPut[i].cbData);
-    memcpy(acData, g_asTestWPut[i].pvDataIn, g_asTestWPut[i].cbDataIn);
-    MBlkCont.b_rptr = acData;
-    MBlkCont.b_wptr = acData + g_asTestWPut[i].cbData;
-    MBlk.b_cont = &MBlkCont;
-    MBlk.b_rptr = (unsigned char *)&IOCBlk;
-    MBlk.b_wptr = (unsigned char *)&IOCBlk + sizeof(IOCBlk);
-    MBlk.b_datap = &DBlk;
-    rc = vbgr0SolWPut(WR(&aQueues[0]), &MBlk);
-    RTTEST_CHECK_MSG(hTest, IOCBlk.ioc_error == g_asTestWPut[i].rcExp,
+    pMBlk->b_datap->db_type = M_IOCTL;
+    pIOCBlk->ioc_cmd = g_asTestWPut[i].iIOCCmd;
+    pIOCBlk->ioc_count = g_asTestWPut[i].cbData;
+    AssertReturnVoid(g_asTestWPut[i].cbData <= MSG_DATA_SIZE);
+    memcpy(pMBlkCont->b_rptr, g_asTestWPut[i].pvDataIn,
+           g_asTestWPut[i].cbDataIn);
+    pMBlk->b_cont = pMBlkCont;
+    rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
+    RTTEST_CHECK_MSG(hTest, pIOCBlk->ioc_error == g_asTestWPut[i].rcExp,
                      (hTest, "i=%u, IOCBlk.ioc_error=%d\n", i,
-                      IOCBlk.ioc_error));
-    RTTEST_CHECK_MSG(hTest, IOCBlk.ioc_count == g_asTestWPut[i].cbDataOut,
-                     (hTest, "i=%u, ioc_count=%u\n", i, IOCBlk.ioc_count));
-    RTTEST_CHECK_MSG(hTest, !memcmp(acData, g_asTestWPut[i].pvDataOut,
+                      pIOCBlk->ioc_error));
+    RTTEST_CHECK_MSG(hTest, pIOCBlk->ioc_count == g_asTestWPut[i].cbDataOut,
+                     (hTest, "i=%u, ioc_count=%u\n", i, pIOCBlk->ioc_count));
+    RTTEST_CHECK_MSG(hTest, !memcmp(pMBlkCont->b_rptr,
+                                    g_asTestWPut[i].pvDataOut,
                                     g_asTestWPut[i].cbDataOut),
                      (hTest, "i=%u\n", i));
     /* Hack to ensure that miocpullup() gets called when needed. */
     if (g_asTestWPut[i].cbData > 0)
-        RTTEST_CHECK_MSG(hTest, MBlk.b_flag == 1, (hTest, "i=%u\n", i));
+        RTTEST_CHECK_MSG(hTest, pMBlk->b_flag == 1, (hTest, "i=%u\n", i));
     if (!g_asTestWPut[i].rcExp)
-        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first = &MBlk,
+        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first == pMBlk,
                          (hTest, "i=%u\n", i));
     if (g_asTestWPut[i].pfnExtra)
-        g_asTestWPut[i].pfnExtra(hTest, WR(&aQueues[0]), &MBlk);
+        if (!g_asTestWPut[i].pfnExtra(hTest, WR(&aQueues[0]), pMBlk))
+            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
+                         __PRETTY_FUNCTION__);
     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
-}
-
+    freemsg(pMBlk);
+}
+
+
+#define USER_ADDRESS 0xfeedbacc
 
 /** Simulate sending a transparent IOCtl to WPut with the parameters from table
@@ -678,13 +685,14 @@
     queue_t aQueues[2];
     dev_t device = 0;
-    struct msgb MBlk, MBlkCont;
-    struct datab DBlk;
-    struct iocblk IOCBlk;
-    struct copyreq *pCopyReq = (struct copyreq *)&IOCBlk;
+    struct msgb *pMBlk = allocb(sizeof(struct iocblk), BPRI_MED);
+    struct msgb *pMBlkCont = allocb(sizeof(void *), BPRI_MED);
+    struct iocblk *pIOCBlk = pMBlk ? (struct iocblk *)pMBlk->b_rptr : NULL;
+    struct copyreq *pCopyReq;
     int rc, cFormat = 0;
-    unsigned char acData[1024];
-
-    if (g_asTestWPut[i].cbDataIn == 0 && g_asTestWPut[i].cbDataOut != 0)
-        return;  /* This case will be handled once the current ones work. */
+
+    /* if (g_asTestWPut[i].cbDataIn == 0 && g_asTestWPut[i].cbDataOut != 0)
+        return; */  /* This case will be handled once the current ones work. */
+    AssertReturnVoid(pMBlk);
+    AssertReturnVoidStmt(pMBlkCont, freemsg(pMBlk));
     RT_ZERO(aQueues);
     doInitQueues(&aQueues[0]);
@@ -693,63 +701,122 @@
     RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
                             == WR(&aQueues[0]), (hTest, "i=%u\n", i));
-    RT_ZERO(MBlk);
-    RT_ZERO(DBlk);
-    RT_ZERO(IOCBlk);
-    RT_ZERO(MBlkCont);
-    RT_ZERO(acData);
-    DBlk.db_type = M_IOCTL;
-    IOCBlk.ioc_cmd = g_asTestWPut[i].iIOCCmd;
-    IOCBlk.ioc_count = TRANSPARENT;
-    AssertReturnVoid(g_asTestWPut[i].cbData <= sizeof(acData));
-    AssertReturnVoid(g_asTestWPut[i].cbDataIn <= g_asTestWPut[i].cbData);
-    AssertReturnVoid(g_asTestWPut[i].cbDataOut <= g_asTestWPut[i].cbData);
-    memcpy(acData, g_asTestWPut[i].pvDataIn, g_asTestWPut[i].cbDataIn);
-    MBlkCont.b_rptr = acData;
-    MBlkCont.b_wptr = acData + g_asTestWPut[i].cbData;
-    MBlk.b_cont = &MBlkCont;
-    MBlk.b_rptr = (unsigned char *)&IOCBlk;
-    MBlk.b_wptr = (unsigned char *)&IOCBlk + sizeof(IOCBlk);
-    MBlk.b_datap = &DBlk;
-    rc = vbgr0SolWPut(WR(&aQueues[0]), &MBlk);
+    pMBlk->b_datap->db_type = M_IOCTL;
+    pIOCBlk->ioc_cmd = g_asTestWPut[i].iIOCCmd;
+    pIOCBlk->ioc_count = TRANSPARENT;
+    *(void **)pMBlkCont->b_rptr = (void *)USER_ADDRESS;
+    pMBlk->b_cont = pMBlkCont;
+    rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
+    pCopyReq = (struct copyreq *)pMBlk->b_rptr;
     RTTEST_CHECK_MSG(hTest, (   (   g_asTestWPut[i].cbDataIn
-                                 && (MBlk.b_datap->db_type == M_COPYIN))
+                                 && (pMBlk->b_datap->db_type == M_COPYIN))
                              || (   g_asTestWPut[i].cbDataOut
-                                 && (MBlk.b_datap->db_type == M_COPYOUT))
+                                 && (pMBlk->b_datap->db_type == M_COPYOUT))
                              || (   (g_asTestWPut[i].rcExp == 0)
-                                 && MBlk.b_datap->db_type == M_IOCACK)
-                             || (MBlk.b_datap->db_type == M_IOCNAK)),
+                                 && pMBlk->b_datap->db_type == M_IOCACK)
+                             || (pMBlk->b_datap->db_type == M_IOCNAK)),
                      (hTest, "i=%u, db_type=%u\n", i,
-                      (unsigned) MBlk.b_datap->db_type));
+                      (unsigned) pMBlk->b_datap->db_type));
     /* Our TRANSPARENT IOCtls can only return non-zero if they have no payload.
      * Others should either return zero or be non-TRANSPARENT only. */
-    if (MBlk.b_datap->db_type == M_IOCNAK)
-        RTTEST_CHECK_MSG(hTest, IOCBlk.ioc_error == g_asTestWPut[i].rcExp,
+    if (pMBlk->b_datap->db_type == M_IOCNAK)
+        RTTEST_CHECK_MSG(hTest, pIOCBlk->ioc_error == g_asTestWPut[i].rcExp,
                          (hTest, "i=%u, IOCBlk.ioc_error=%d\n", i,
-                          IOCBlk.ioc_error));
+                          pIOCBlk->ioc_error));
     if (g_asTestWPut[i].cbData)
     {
-        RTTEST_CHECK_MSG(hTest, pCopyReq->cq_addr == acData,
+        RTTEST_CHECK_MSG(hTest, pCopyReq->cq_addr == (char *)USER_ADDRESS,
+                         (hTest, "i=%u, cq_addr=%p\n", i, pCopyReq->cq_addr));
+        RTTEST_CHECK_MSG(   hTest, pCopyReq->cq_size
+                         ==   g_asTestWPut[i].cbDataIn
+                            ? g_asTestWPut[i].cbDataIn
+                            : g_asTestWPut[i].cbDataOut,
+                         (hTest, "i=%u, cq_size=%llu\n", i,
+                          (unsigned long long)pCopyReq->cq_size));
+    }
+    /* Implementation detail - check that the private pointer is correctly
+     * set to the user address *for two direction IOCtls* or NULL otherwise. */
+    if (g_asTestWPut[i].cbDataIn && g_asTestWPut[i].cbDataOut)
+        RTTEST_CHECK_MSG(hTest, pCopyReq->cq_private == (mblk_t *)USER_ADDRESS,
+                         (hTest, "i=%u, cq_private=%p\n", i,
+                          pCopyReq->cq_private));
+    else if (   (pMBlk->b_datap->db_type == M_COPYIN)
+             || (pMBlk->b_datap->db_type == M_COPYOUT))
+        RTTEST_CHECK_MSG(hTest, !pCopyReq->cq_private,
+                         (hTest, "i=%u, cq_private=%p\n", i,
+                          pCopyReq->cq_private));
+    if (!g_asTestWPut[i].rcExp)
+        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first == pMBlk,
+                         (hTest, "i=%u\n", i));
+    if (g_asTestWPut[i].pfnExtra && !g_asTestWPut[i].cbData)
+        if (!g_asTestWPut[i].pfnExtra(hTest, WR(&aQueues[0]), pMBlk))
+            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
+                         __PRETTY_FUNCTION__);
+    vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
+    freemsg(pMBlk);
+}
+
+
+/** Simulate sending follow-on IOCData messages to a transparent IOCtl to WPut
+ * with the parameters from table line @a i. */
+void testWPutIOCDataIn(RTTEST hTest, unsigned i)
+{
+    queue_t aQueues[2];
+    dev_t device = 0;
+    struct msgb *pMBlk = allocb(sizeof(struct copyresp), BPRI_MED);
+    struct msgb *pMBlkCont = allocb(MSG_DATA_SIZE, BPRI_MED);
+    struct copyresp *pCopyResp = pMBlk ? (struct copyresp *)pMBlk->b_rptr
+                                       : NULL;
+    void *pvData = pMBlkCont ? pMBlkCont->b_rptr : NULL;
+    struct copyreq *pCopyReq;
+    int rc, cFormat = 0;
+
+    AssertReturnVoid(pMBlk);
+    AssertReturnVoidStmt(pMBlkCont, freemsg(pMBlk));
+    AssertReturnVoid(g_asTestWPut[i].cbDataIn);
+    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%s: i=%u\n", __PRETTY_FUNCTION__,
+                 i);
+    RT_ZERO(aQueues);
+    doInitQueues(&aQueues[0]);
+    rc = vbgr0SolOpen(RD(&aQueues[0]), &device, 0, 0, NULL);
+    RTTEST_CHECK_MSG(hTest, rc == 0, (hTest, "i=%u, rc=%d\n", i, rc));
+    RTTEST_CHECK_MSG(hTest,    g_aOpenNodeStates[1].pWriteQueue
+                            == WR(&aQueues[0]), (hTest, "i=%u\n", i));
+    pMBlk->b_datap->db_type = M_IOCDATA;
+    pCopyResp->cp_cmd = g_asTestWPut[i].iIOCCmd;
+    AssertReturnVoid(g_asTestWPut[i].cbData <= MSG_DATA_SIZE);
+    memcpy(pMBlkCont->b_rptr, g_asTestWPut[i].pvDataIn, g_asTestWPut[i].cbDataIn);
+    pMBlk->b_cont = pMBlkCont;
+    rc = vbgr0SolWPut(WR(&aQueues[0]), pMBlk);
+    pCopyReq = (struct copyreq *)pMBlk->b_rptr;
+    RTTEST_CHECK_MSG(hTest, (   (   g_asTestWPut[i].cbDataOut
+                                 && (pMBlk->b_datap->db_type == M_COPYOUT))
+                             || (   (g_asTestWPut[i].rcExp == 0)
+                                 && pMBlk->b_datap->db_type == M_IOCACK)
+                             || (pMBlk->b_datap->db_type == M_IOCNAK)),
+                     (hTest, "i=%u, db_type=%u\n", i,
+                      (unsigned) pMBlk->b_datap->db_type));
+    if (g_asTestWPut[i].cbDataOut)
+    {
+        RTTEST_CHECK_MSG(hTest, pCopyReq->cq_addr == (char *)pvData,
                          (hTest, "i=%u, cq_addr=%p\n", i, pCopyReq->cq_addr));
         RTTEST_CHECK_MSG(hTest, pCopyReq->cq_size == g_asTestWPut[i].cbData,
                          (hTest, "i=%u, cq_size=%llu\n", i,
                           (unsigned long long)pCopyReq->cq_size));
-    }
-    /* Implementation detail - check that the private pointer is correctly
-     * set to the user address *for two direction IOCtls* or NULL otherwise. */
-    if (g_asTestWPut[i].cbDataIn && g_asTestWPut[i].cbDataOut)
-        RTTEST_CHECK_MSG(hTest, pCopyReq->cq_private == acData,
-                         (hTest, "i=%u, cq_private=%p\n", i,
-                          pCopyReq->cq_private));
-    else if (   (MBlk.b_datap->db_type == M_COPYIN)
-             || (MBlk.b_datap->db_type == M_COPYOUT))
-        RTTEST_CHECK_MSG(hTest, !pCopyReq->cq_private,
-                         (hTest, "i=%u, cq_private=%p\n", i,
-                          pCopyReq->cq_private));
+        RTTEST_CHECK_MSG(hTest, !memcmp(pvData, g_asTestWPut[i].pvDataOut,
+                                        g_asTestWPut[i].cbDataOut),
+                         (hTest, "i=%u\n", i));
+    }
+    RTTEST_CHECK_MSG(hTest, !pCopyReq->cq_private,
+                     (hTest, "i=%u, cq_private=%p\n", i,
+                      pCopyReq->cq_private));
     if (!g_asTestWPut[i].rcExp)
-        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first = &MBlk,
+        RTTEST_CHECK_MSG(hTest, RD(&aQueues[0])->q_first == pMBlk,
                          (hTest, "i=%u\n", i));
-    if (g_asTestWPut[i].pfnExtra && !g_asTestWPut[i].cbData)
-        g_asTestWPut[i].pfnExtra(hTest, WR(&aQueues[0]), &MBlk);
+    if (g_asTestWPut[i].pfnExtra && !g_asTestWPut[i].cbDataOut)
+        if (!g_asTestWPut[i].pfnExtra(hTest, WR(&aQueues[0]), pMBlk))
+            RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Called from %s.\n",
+                         __PRETTY_FUNCTION__);
     vbgr0SolClose(RD(&aQueues[1]), 0, NULL);
+    freemsg(pMBlk);
 }
 #endif
@@ -951,6 +1018,4 @@
         int err;
 
-        if (cbData < cbTransparent)
-            return EINVAL;
         if (!pMBlk->b_cont)
             return EINVAL;
@@ -1001,5 +1066,5 @@
 	else if (enmDirection == OUT)
     {
-        mblk_t *pMBlkOut = allocb(cbOut, BPRI_MED);
+        mblk_t *pMBlkOut = allocb(cbTransparent, BPRI_MED);
         void *pvData;
 
@@ -1567,5 +1632,5 @@
 {
     queue_t *pReadQueue = RD(pState->pWriteQueue);
-    mblk_t *pMBlk = allocb(sizeof(Firm_event, BPRI_HI));
+    mblk_t *pMBlk = allocb(sizeof(Firm_event), BPRI_HI);
     Firm_event *pEvent;
     AssertReturnVoid(cEvent == LOC_X_ABSOLUTE || cEvent == LOC_Y_ABSOLUTE);
Index: /trunk/src/VBox/Additions/common/VBoxGuest/testcase/solaris.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/testcase/solaris.h	(revision 41019)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/testcase/solaris.h	(revision 41020)
@@ -40,4 +40,5 @@
 #define MOD_NOAUTOUNLOAD        0x1
 
+#define M_DATA          0x00
 #define M_BREAK         0x08
 #define M_PASSFP        0x09
@@ -70,4 +71,8 @@
 #define M_CMD           0x93
 
+#define BPRI_LO         1
+#define BPRI_MED        2
+#define BPRI_HI         3
+
 #define FLUSHALL        1
 #define FLUSHDATA       0
@@ -229,7 +234,11 @@
     uint_t      ioc_id;
     uint_t      ioc_flag;
-    uint_t      ioc_count;
+    size_t      ioc_count;
     int         ioc_rval;
     int         ioc_error;
+#if defined(RT_ARCH_AMD64)  /* Actually this should be LP64. */
+    int         dummy;  /* For simplicity, to ensure the structure size matches
+                           struct copyreq. */
+#endif
 };
 
@@ -311,5 +320,4 @@
 
 #define cmn_err(...) do {} while(0)
-#define allocb(...) NULL
 #define mod_remove(...) 0
 #define mod_info(...) 0
@@ -332,5 +340,4 @@
 #define qprocsoff(...) do {} while(0)
 #define flushq(...) do {} while(0)
-#define freemsg(...) do {} while(0)
 #define putnext(...) do {} while(0)
 #define ddi_get_instance(...) 0
@@ -375,4 +382,6 @@
                      mblk_t *pMBlkData);
 extern void qreply(queue_t *pQueue, mblk_t *pMBlk);
+extern mblk_t *allocb(size_t cb, uint_t cPrio);
+extern void freemsg(mblk_t *pMsg);
 
 /* API stubs with simple logic */
Index: /trunk/src/VBox/Additions/common/VBoxGuest/testcase/tstVBoxGuest-solaris.c
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/testcase/tstVBoxGuest-solaris.c	(revision 41019)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/testcase/tstVBoxGuest-solaris.c	(revision 41020)
@@ -20,4 +20,5 @@
 
 #include "solaris.h"
+#include <iprt/alloc.h>
 
 /******************************************************************************
@@ -75,5 +76,5 @@
     pCopyReq->cq_private = pvState;
     pCopyReq->cq_size = cbData;
-    pCopyReq->cq_addr = pvUser ? pvUser : pMBlk->b_cont->b_rptr;
+    pCopyReq->cq_addr = pvUser ? pvUser : *(void **)pMBlk->b_cont->b_rptr;
     if (pMBlk->b_cont)
     {
@@ -97,5 +98,5 @@
     pCopyReq->cq_private = pvState;
     pCopyReq->cq_size = cbData;
-    pCopyReq->cq_addr = pvUser ? pvUser : pMBlk->b_cont->b_rptr;
+    pCopyReq->cq_addr = pvUser ? pvUser : *(void **)pMBlk->b_cont->b_rptr;
     if (pMBlkData)
     {
@@ -113,2 +114,36 @@
     OTHERQ(pQueue)->q_first = pMBlk;
 }
+
+/** @todo reference counting */
+mblk_t *allocb(size_t cb, uint_t cPrio)
+{
+    unsigned char *pch = RTMemAllocZ(cb);
+    struct msgb *pMBlk = (struct msgb *)RTMemAllocZ(sizeof(struct msgb));
+    struct datab *pDBlk = (struct datab *)RTMemAllocZ(sizeof(struct datab));
+    if (!pch || !pMBlk || !pDBlk)
+    {
+        RTMemFree(pch);
+        RTMemFree(pMBlk);
+        RTMemFree(pDBlk);
+        return NULL;
+    }
+    NOREF(cPrio);
+    pMBlk->b_rptr = pch;
+    pMBlk->b_wptr = pMBlk->b_rptr + cb;
+    pMBlk->b_datap = pDBlk;
+    pDBlk->db_base = pMBlk->b_rptr;
+    pDBlk->db_lim = pMBlk->b_wptr;
+    pDBlk->db_type = M_DATA;
+    return pMBlk;
+}
+
+/** @todo reference counting */
+void freemsg(mblk_t *pMBlk)
+{
+    if (!pMBlk)
+        return;
+    RTMemFree(pMBlk->b_rptr);
+    RTMemFree(pMBlk->b_datap);
+    freemsg(pMBlk->b_cont);
+    RTMemFree(pMBlk);
+}
