Index: trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
===================================================================
--- trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 38192)
+++ trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 38210)
@@ -19,8 +19,12 @@
 #define ____H_GUESTIMPLPRIVATE
 
-#include "VirtualBoxBase.h"
+#include <VBox/com/com.h>
+#include <VBox/com/string.h>
+#include <VBox/com/VirtualBox.h>
 
 #include <map>
 #include <vector>
+
+using namespace com;
 
 #ifdef VBOX_WITH_GUEST_CONTROL
@@ -51,13 +55,9 @@
 public:
 
-    void Destroy();
+    int AddData(const BYTE *pbData, size_t cbData);
 
     void ClearPairs();
 
-    const char* GetString(const char *pszKey);
-
-    int GetUInt32Ex(const char *pszKey, uint32_t *puVal);
-
-    uint32_t GetUInt32(const char *pszKey);
+    void Destroy();
 
     int GetInt64Ex(const char *pszKey, int64_t *piVal);
@@ -67,5 +67,11 @@
     size_t GetNumPairs();
 
-    int AddData(const BYTE *pbData, size_t cbData);
+    uint32_t GetOffset();
+
+    const char* GetString(const char *pszKey);
+
+    int GetUInt32Ex(const char *pszKey, uint32_t *puVal);
+
+    uint32_t GetUInt32(const char *pszKey);
 
     int Parse();
Index: trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp	(revision 38192)
+++ trunk/src/VBox/Main/src-client/GuestCtrlIO.cpp	(revision 38210)
@@ -44,112 +44,4 @@
 }
 
-/**
- * Destroys the stored stream pairs.
- */
-void GuestProcessStream::Destroy()
-{
-    ClearPairs();
-
-    if (m_pbBuffer)
-        RTMemFree(m_pbBuffer);
-}
-
-void GuestProcessStream::ClearPairs()
-{
-    for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++)
-    {
-        if (it->second.pszValue)
-            RTMemFree(it->second.pszValue);
-    }
-
-    m_mapPairs.clear();
-}
-
-/**
- * Returns a 32-bit unsigned integer of a specified key.
- *
- * @return  uint32_t            Value to return, 0 if not found / on failure.
- * @param   pszKey              Name of key to get the value for.
- */
-const char* GuestProcessStream::GetString(const char *pszKey)
-{
-    AssertPtrReturn(pszKey, NULL);
-
-    try
-    {
-        GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
-        if (itPairs != m_mapPairs.end())
-            return itPairs->second.pszValue;
-    }
-    catch (const std::exception &ex)
-    {
-        NOREF(ex);
-    }
-    return NULL;
-}
-
-int GuestProcessStream::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
-{
-    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
-    AssertPtrReturn(puVal, VERR_INVALID_POINTER);
-    const char *pszValue = GetString(pszKey);
-    if (pszValue)
-    {
-        *puVal = RTStrToUInt32(pszValue);
-        return VINF_SUCCESS;
-    }
-    return VERR_NOT_FOUND;
-}
-
-/**
- * Returns a 32-bit unsigned integer of a specified key.
- *
- * @return  uint32_t            Value to return, 0 if not found / on failure.
- * @param   pszKey              Name of key to get the value for.
- */
-uint32_t GuestProcessStream::GetUInt32(const char *pszKey)
-{
-    uint32_t uVal;
-    if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
-        return uVal;
-    return 0;
-}
-
-int GuestProcessStream::GetInt64Ex(const char *pszKey, int64_t *piVal)
-{
-    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
-    AssertPtrReturn(piVal, VERR_INVALID_POINTER);
-    const char *pszValue = GetString(pszKey);
-    if (pszValue)
-    {
-        *piVal = RTStrToInt64(pszValue);
-        return VINF_SUCCESS;
-    }
-    return VERR_NOT_FOUND;
-}
-
-/**
- * Returns a 64-bit integer of a specified key.
- *
- * @return  int64_t             Value to return, 0 if not found / on failure.
- * @param   pszKey              Name of key to get the value for.
- */
-int64_t GuestProcessStream::GetInt64(const char *pszKey)
-{
-    int64_t iVal;
-    if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
-        return iVal;
-    return 0;
-}
-
-/**
- * Returns the current number of stream pairs.
- *
- * @return  uint32_t            Current number of stream pairs.
- */
-size_t GuestProcessStream::GetNumPairs()
-{
-    return m_mapPairs.size();
-}
 
 int GuestProcessStream::AddData(const BYTE *pbData, size_t cbData)
@@ -214,4 +106,118 @@
 
     return rc;
+}
+
+void GuestProcessStream::ClearPairs()
+{
+    for (GuestCtrlStreamPairsIter it = m_mapPairs.begin(); it != m_mapPairs.end(); it++)
+    {
+        if (it->second.pszValue)
+            RTMemFree(it->second.pszValue);
+    }
+
+    m_mapPairs.clear();
+}
+
+/**
+ * Destroys the stored stream pairs.
+ */
+void GuestProcessStream::Destroy()
+{
+    ClearPairs();
+
+    if (m_pbBuffer)
+        RTMemFree(m_pbBuffer);
+}
+
+int GuestProcessStream::GetInt64Ex(const char *pszKey, int64_t *piVal)
+{
+    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
+    AssertPtrReturn(piVal, VERR_INVALID_POINTER);
+    const char *pszValue = GetString(pszKey);
+    if (pszValue)
+    {
+        *piVal = RTStrToInt64(pszValue);
+        return VINF_SUCCESS;
+    }
+    return VERR_NOT_FOUND;
+}
+
+/**
+ * Returns a 64-bit integer of a specified key.
+ *
+ * @return  int64_t             Value to return, 0 if not found / on failure.
+ * @param   pszKey              Name of key to get the value for.
+ */
+int64_t GuestProcessStream::GetInt64(const char *pszKey)
+{
+    int64_t iVal;
+    if (RT_SUCCESS(GetInt64Ex(pszKey, &iVal)))
+        return iVal;
+    return 0;
+}
+
+/**
+ * Returns the current number of stream pairs.
+ *
+ * @return  uint32_t            Current number of stream pairs.
+ */
+size_t GuestProcessStream::GetNumPairs()
+{
+    return m_mapPairs.size();
+}
+
+uint32_t GuestProcessStream::GetOffset()
+{
+    return m_cbOffset;
+}
+
+/**
+ * Returns a 32-bit unsigned integer of a specified key.
+ *
+ * @return  uint32_t            Value to return, 0 if not found / on failure.
+ * @param   pszKey              Name of key to get the value for.
+ */
+const char* GuestProcessStream::GetString(const char *pszKey)
+{
+    AssertPtrReturn(pszKey, NULL);
+
+    try
+    {
+        GuestCtrlStreamPairsIterConst itPairs = m_mapPairs.find(Utf8Str(pszKey));
+        if (itPairs != m_mapPairs.end())
+            return itPairs->second.pszValue;
+    }
+    catch (const std::exception &ex)
+    {
+        NOREF(ex);
+    }
+    return NULL;
+}
+
+int GuestProcessStream::GetUInt32Ex(const char *pszKey, uint32_t *puVal)
+{
+    AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
+    AssertPtrReturn(puVal, VERR_INVALID_POINTER);
+    const char *pszValue = GetString(pszKey);
+    if (pszValue)
+    {
+        *puVal = RTStrToUInt32(pszValue);
+        return VINF_SUCCESS;
+    }
+    return VERR_NOT_FOUND;
+}
+
+/**
+ * Returns a 32-bit unsigned integer of a specified key.
+ *
+ * @return  uint32_t            Value to return, 0 if not found / on failure.
+ * @param   pszKey              Name of key to get the value for.
+ */
+uint32_t GuestProcessStream::GetUInt32(const char *pszKey)
+{
+    uint32_t uVal;
+    if (RT_SUCCESS(GetUInt32Ex(pszKey, &uVal)))
+        return uVal;
+    return 0;
 }
 
Index: trunk/src/VBox/Main/testcase/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/testcase/Makefile.kmk	(revision 38192)
+++ trunk/src/VBox/Main/testcase/Makefile.kmk	(revision 38210)
@@ -23,5 +23,5 @@
 #
 ifndef VBOX_ONLY_SDK
- if defined(VBOX_WITH_TESTCASES) || "$(USERNAME)" == "umoeller"
+ if defined(VBOX_WITH_TESTCASES)
   PROGRAMS       += \
 	tstAPI \
@@ -69,4 +69,5 @@
 endif
 
+
 #
 # tstOVF
@@ -97,4 +98,5 @@
 	ovf-winxp-vbox-sharedfolders/winxp.ovf=>ovf-winxp-vbox-sharedfolders/winxp.ovf
 endif
+
 
 #
@@ -144,9 +146,19 @@
 tstCollector_LDFLAGS.win     += psapi.lib powrprof.lib
 
+
 #
 # tstGuestCtrlParseBuffer
 #
-tstGuestCtrlParseBuffer_TEMPLATE = VBOXR3TSTNPEXE
-tstGuestCtrlParseBuffer_SOURCES = tstGuestCtrlParseBuffer.cpp
+tstGuestCtrlParseBuffer_TEMPLATE = VBOXMAINCLIENTEXE
+tstGuestCtrlParseBuffer_SOURCES  = \
+	tstGuestCtrlParseBuffer.cpp \
+	../src-client/GuestCtrlIO.cpp
+tstGuestCtrlParseBuffer_INCS     = ../include
+ifeq ($(KBUILD_TARGET),win) ## @todo just add this to the template.
+ tstGuestCtrlParseBuffer_DEPS    = $(VBOX_PATH_SDK)/bindings/mscom/include/VirtualBox.h
+else
+ tstGuestCtrlParseBuffer_DEPS    = $(VBOX_PATH_SDK)/bindings/xpcom/include/VirtualBox_XPCOM.h
+endif
+
 
 #
Index: trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp
===================================================================
--- trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp	(revision 38192)
+++ trunk/src/VBox/Main/testcase/tstGuestCtrlParseBuffer.cpp	(revision 38210)
@@ -18,8 +18,15 @@
  */
 
-#include <map>
-
-#include <iprt/string.h>
-#include <iprt/cpp/ministring.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../include/GuestCtrlImplPrivate.h"
+
+using namespace com;
+
+#define LOG_ENABLED
+#define LOG_GROUP LOG_GROUP_MAIN
+#define LOG_INSTANCE NULL
+#include <VBox/log.h>
 
 #include <iprt/test.h>
@@ -29,6 +36,4 @@
 # define BYTE uint8_t
 #endif
-
-/** @todo Use original source of GuestCtrlImpl.cpp! */
 
 typedef struct VBOXGUESTCTRL_BUFFER_VALUE
@@ -101,122 +106,4 @@
 };
 
-int outputBufferParse(const BYTE *pbData, size_t cbData, uint32_t *puOffset, GuestBufferMap& mapBuf)
-{
-    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
-    AssertReturn(cbData, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(puOffset, VERR_INVALID_POINTER);
-    AssertReturn(*puOffset < cbData, VERR_INVALID_PARAMETER);
-
-    int rc = VINF_SUCCESS;
-
-    size_t uCur = *puOffset;
-    for (;uCur < cbData;)
-    {
-        const char *pszStart = (char*)&pbData[uCur];
-        const char *pszEnd = pszStart;
-
-        /* Search end of current pair (key=value\0). */
-        while (uCur++ < cbData)
-        {
-            if (*pszEnd == '\0')
-                break;
-            pszEnd++;
-        }
-
-        size_t uPairLen = pszEnd - pszStart;
-        if (uPairLen)
-        {
-            const char *pszSep = pszStart;
-            while (   *pszSep != '='
-                   &&  pszSep != pszEnd)
-            {
-                pszSep++;
-            }
-
-            /* No separator found (or incomplete key=value pair)? */
-            if (   pszSep == pszStart
-                || pszSep == pszEnd)
-            {
-                *puOffset =  uCur - uPairLen - 1;
-                rc = VERR_MORE_DATA;
-            }
-
-            if (RT_FAILURE(rc))
-                break;
-
-            size_t uKeyLen = pszSep - pszStart;
-            size_t uValLen = pszEnd - (pszSep + 1);
-
-            /* Get key (if present). */
-            if (uKeyLen)
-            {
-                Assert(pszSep > pszStart);
-                char *pszKey = (char*)RTMemAllocZ(uKeyLen + 1);
-                if (!pszKey)
-                {
-                    rc = VERR_NO_MEMORY;
-                    break;
-                }
-                memcpy(pszKey, pszStart, uKeyLen);
-
-                mapBuf[RTCString(pszKey)].pszValue = NULL;
-
-                /* Get value (if present). */
-                if (uValLen)
-                {
-                    Assert(pszEnd > pszSep);
-                    char *pszVal = (char*)RTMemAllocZ(uValLen + 1);
-                    if (!pszVal)
-                    {
-                        rc = VERR_NO_MEMORY;
-                        break;
-                    }
-                    memcpy(pszVal, pszSep + 1, uValLen);
-
-                    mapBuf[RTCString(pszKey)].pszValue = pszVal;
-                }
-
-                RTMemFree(pszKey);
-
-                *puOffset += uCur - *puOffset;
-            }
-        }
-        else /* No pair detected, check for a new block. */
-        {
-            do
-            {
-                if (*pszEnd == '\0')
-                {
-                    *puOffset = uCur;
-                    rc = VERR_MORE_DATA;
-                    break;
-                }
-                pszEnd++;
-            } while (++uCur < cbData);
-        }
-
-        if (RT_FAILURE(rc))
-            break;
-    }
-
-    RT_CLAMP(*puOffset, 0, cbData);
-
-    return rc;
-}
-
-void tstOutputAndDestroyMap(GuestBufferMap &bufMap)
-{
-    for (GuestBufferMapIter it = bufMap.begin(); it != bufMap.end(); it++)
-    {
-        RTTestIPrintf(RTTESTLVL_DEBUG, "\t%s -> %s\n",
-                      it->first.c_str(), it->second.pszValue ? it->second.pszValue : "<undefined>");
-
-        if (it->second.pszValue)
-            RTMemFree(it->second.pszValue);
-    }
-
-    bufMap.clear();
-}
-
 int main()
 {
@@ -226,4 +113,12 @@
         return rc;
     RTTestBanner(hTest);
+
+    RTPrintf("Initializing COM...\n");
+    rc = com::Initialize();
+    if (FAILED(rc))
+    {
+        RTPrintf("ERROR: failed to initialize COM!\n");
+        return rc;
+    }
 
     RTTestIPrintf(RTTESTLVL_INFO, "Doing basic tests ...\n");
@@ -241,11 +136,18 @@
     for (iTest; iTest < RT_ELEMENTS(aTests); iTest++)
     {
-        GuestBufferMap bufMap;
         uint32_t uOffset = aTests[iTest].uOffsetStart;
 
-        int iResult = outputBufferParse((BYTE*)aTests[iTest].pbData, aTests[iTest].cbData,
-                                        &uOffset, bufMap);
-
         RTTestIPrintf(RTTESTLVL_DEBUG, "=> Test #%u\n", iTest);
+
+        GuestProcessStream stream;
+        int iResult = stream.AddData((BYTE*)aTests[iTest].pbData, aTests[iTest].cbData);
+        if (RT_FAILURE(iResult))
+        {
+            RTTestFailed(hTest, "\tAdding data returned %Rrc, expected VINF_SUCCESS",
+                         iResult);
+            continue;
+        }
+
+        iResult = stream.Parse();
 
         if (iResult != aTests[iTest].iResult)
@@ -254,10 +156,10 @@
                          iResult, aTests[iTest].iResult);
         }
-        else if (bufMap.size() != aTests[iTest].uMapElements)
+        else if (stream.GetNumPairs() != aTests[iTest].uMapElements)
         {
             RTTestFailed(hTest, "\tMap has %u elements, expected %u",
-                         bufMap.size(), aTests[iTest].uMapElements);
-        }
-        else if (uOffset != aTests[iTest].uOffsetAfter)
+                         stream.GetNumPairs(), aTests[iTest].uMapElements);
+        }
+        else if (stream.GetOffset() != aTests[iTest].uOffsetAfter)
         {
             RTTestFailed(hTest, "\tOffset %u wrong, expected %u",
@@ -279,6 +181,4 @@
             }
         }
-
-        tstOutputAndDestroyMap(bufMap);
     }
 
@@ -289,44 +189,36 @@
         RTTestIPrintf(RTTESTLVL_DEBUG, "=> Block test #%u\n", iTest);
 
-        int iResult;
-
-        GuestBufferMap bufMap;
-        uint32_t uOffset = 0;
-        uint32_t uNumBlocks = 0;
-
-        while (uOffset < aTests2[iTest].cbData - 1)
-        {
-            iResult = outputBufferParse((BYTE*)aTests2[iTest].pbData, aTests2[iTest].cbData,
-                                        &uOffset, bufMap);
-            RTTestIPrintf(RTTESTLVL_DEBUG, "\tReturned with %Rrc\n", iResult);
-            if (   iResult == VINF_SUCCESS
-                || iResult == VERR_MORE_DATA)
-            {
-                if (bufMap.size()) /* Only count block which have some valid data. */
+        GuestProcessStream stream;
+        int iResult = stream.AddData((BYTE*)aTests2[iTest].pbData, aTests2[iTest].cbData);
+        if (RT_SUCCESS(iResult))
+        {
+            uint32_t uNumBlocks = 0;
+
+            do
+            {
+                iResult = stream.Parse();
+                if (iResult == VERR_MORE_DATA)
                     uNumBlocks++;
-
-                tstOutputAndDestroyMap(bufMap);
-
-                RTTestIPrintf(RTTESTLVL_DEBUG, "\tNext offset %u (total: %u)\n",
-                              uOffset, aTests2[iTest].cbData);
+                if (uNumBlocks > 32)
+                    break; /* Give up if unreasonable big. */
+            } while (iResult == VERR_MORE_DATA);
+
+            if (iResult != aTests2[iTest].iResult)
+            {
+                RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc",
+                             iResult, aTests2[iTest].iResult);
             }
-            else
-                break;
-
-            if (uNumBlocks > 32)
-                break; /* Give up if unreasonable big. */
-        }
-
-        if (iResult != aTests2[iTest].iResult)
-        {
-            RTTestFailed(hTest, "\tReturned %Rrc, expected %Rrc",
-                         iResult, aTests2[iTest].iResult);
-        }
-        else if (uNumBlocks != aTests2[iTest].uNumBlocks)
-        {
-            RTTestFailed(hTest, "\tReturned %u blocks, expected %u\n",
-                         uNumBlocks, aTests2[iTest].uNumBlocks);
-        }
+            else if (uNumBlocks != aTests2[iTest].uNumBlocks)
+            {
+                RTTestFailed(hTest, "\tReturned %u blocks, expected %u\n",
+                             uNumBlocks, aTests2[iTest].uNumBlocks);
+            }
+        }
+        else
+            RTTestFailed(hTest, "\tAdding data failed with %Rrc", iResult);
     }
+
+    RTPrintf("Shutting down COM...\n");
+    com::Shutdown();
 
     /*
