Index: trunk/src/VBox/Main/src-helper-apps/os2/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/src-helper-apps/os2/Makefile.kmk	(revision 93116)
+++ trunk/src/VBox/Main/src-helper-apps/os2/Makefile.kmk	(revision 93120)
@@ -23,16 +23,17 @@
 # This is checked in as a binary, this is just the makefile for re-builting it.
 #
-override DEFS.os2 = RT_OS_OS2 # HACK ALERT!
-PROGRAMS += os2_util
-os2_util_TOOL         = OPENWATCOM-16
-os2_util_ASTOOL       = OPENWATCOM-16
-os2_util_LDTOOL       = OPENWATCOM-WL
-os2_util_BLD_TRG      = os2
-os2_util_BLD_TRG_ARCH = x86
-os2_util_INST         = $(INST_UNATTENDED_TEMPLATES)
-os2_util_MODE         = a+r,u+w
-os2_util_DEFS         = IN_RING3
-os2_util_CFLAGS       = -zl -s -ml
-os2_util_LDFLAGS      = \
+ifdef VBOX_WITH_OPEN_WATCOM
+ PROGRAMS += os2_util
+endif
+os2_util_TOOL           = OPENWATCOM-16
+os2_util_ASTOOL         = OPENWATCOM-16
+os2_util_LDTOOL         = OPENWATCOM-WL
+os2_util_BLD_TRG        = os2
+os2_util_BLD_TRG_ARCH   = x86
+os2_util_INST           = $(INST_UNATTENDED_TEMPLATES)
+os2_util_MODE           = a+r,u+w
+os2_util_DEFS           = IN_RING3
+os2_util_CFLAGS         = -zl -s -ml -os
+os2_util_LDFLAGS        = \
 	SYSTEM os2 \
 	OPTION START=_Os2UtilMain \
@@ -41,6 +42,11 @@
 	OPTION MANYAUTODATA \
 	SEGMENT IOPL IOPL EXECUTEREAD
-os2_util_INCS         = $(PATH_TOOL_OPENWATCOM)/h/os21x
-os2_util_SOURCES      = os2_util.c os2_utilA.asm
+if 0
+os2_util_LDFLAGS       += Debug Watcom All
+os2_util_CFLAGS        += -d2 -hw
+endif
+
+os2_util_INCS           = $(PATH_TOOL_OPENWATCOM)/h/os21x
+os2_util_SOURCES        = os2_util.c os2_utilA.asm
 
 include $(FILE_KBUILD_SUB_FOOTER)
Index: trunk/src/VBox/Main/src-helper-apps/os2/os2_util.c
===================================================================
--- trunk/src/VBox/Main/src-helper-apps/os2/os2_util.c	(revision 93116)
+++ trunk/src/VBox/Main/src-helper-apps/os2/os2_util.c	(revision 93120)
@@ -28,4 +28,6 @@
 #include <VBox/log.h>
 
+#include "VBox/version.h"
+
 
 /*********************************************************************************************************************************
@@ -79,4 +81,18 @@
 
 
+/** strchr-like function. */
+static char __far *MyStrChr(const char __far *psz, char chNeedle)
+{
+    char ch;
+    while ((ch = *psz) != '\0')
+    {
+        if (ch == chNeedle)
+            return (char __far *)psz;
+        psz++;
+    }
+    return NULL;
+}
+
+
 /** memcpy-like function.   */
 static void *MyMemCopy(void __far *pvDst, void const __far *pvSrc, USHORT cb)
@@ -134,5 +150,27 @@
     MyOutNum(rc);
     MyOutStr("\r\n");
-    DosExit(EXIT_PROCESS, 0);
+    DosExit(EXIT_PROCESS, 1);
+}
+
+
+static void MyApiError3AndQuit(PSZ pszOperation, PSZ psz2, PSZ psz3, USHORT rc)
+{
+    MyOutStr("Os2Util: error: ");
+    MyOutStr(pszOperation);
+    MyOutStr(psz2);
+    MyOutStr(psz3);
+    MyOutStr(" failed: ");
+    MyOutNum(rc);
+    MyOutStr("\r\n");
+    DosExit(EXIT_PROCESS, 1);
+}
+
+
+static void MySyntaxErrorAndQuit(PSZ pszMsg)
+{
+    MyOutStr("Os2Util: syntax error: ");
+    MyOutStr(pszMsg);
+    MyOutStr("\r\n");
+    DosExit(EXIT_PROCESS, 1);
 }
 
@@ -160,4 +198,5 @@
          * Write out buffered data
          */
+        /** @todo this does not seem to work. */
         pBuf = g_pBufferHead;
         while (pBuf)
@@ -234,16 +273,113 @@
 
 
+/**
+ * Waits for the child progress to complete, returning it's status code.
+ */
+static void DoWait(PID pidChild, USHORT idSession, HQUEUE hQueue, PRESULTCODES pResultCodes)
+{
+    /*
+     * Can we use DosCwait?
+     */
+    if (idSession == 0 && hQueue == NULL)
+    {
+        for (;;)
+        {
+            PID pidIgnored;
+            USHORT rc = DosCwait(DCWA_PROCESS, DCWW_WAIT, pResultCodes, &pidIgnored, pidChild);
+            if (rc == NO_ERROR)
+                break;
+            if (rc != ERROR_INTERRUPT)
+            {
+                MyOutStr("Os2Util: error: DosCwait(DCWA_PROCESS,DCWW_WAIT,,,");
+                MyOutNum(pidChild);
+                MyOutStr(") failed: ");
+                MyOutNum(rc);
+                MyOutStr("\r\n");
+            }
+        }
+    }
+    else
+    {
+        /*
+         * No we have to use the queue interface to the session manager.
+         */
+        for (;;)
+        {
+            ULONG   ulAdderPidAndEvent = 0;
+            PUSHORT pausData           = NULL;
+            USHORT  cbData             = 0;
+            BYTE    bPriority          = 0;
+            HSEM    hSem               = NULL;
+            USHORT rc = DosReadQueue(hQueue, &ulAdderPidAndEvent, &cbData, (PULONG)&pausData,
+                                     0 /*uElementCode*/, 0 /* fNoWait */, &bPriority, &hSem);
+            if (rc == NO_ERROR)
+            {
+                if (cbData >= sizeof(USHORT) * 2)
+                {
+                    USHORT idTermSession = pausData[0];
+                    USHORT uExitCode     = pausData[1];
+                    if (idTermSession == idSession)
+                    {
+                        pResultCodes->codeTerminate = 0;
+                        pResultCodes->codeResult    = uExitCode;
+                        break;
+                    }
+                    if (1)
+                    {
+                        MyOutStr("OutUtil: info: idTermSession=");
+                        MyOutNum(idTermSession);
+                        MyOutStr(" uExitCode=");
+                        MyOutNum(uExitCode);
+                        MyOutStr("\r\n");
+                    }
+                }
+                else
+                {
+                    MyOutStr("OutUtil: warning: bogus queue element size: cbData=");
+                    MyOutNum(cbData);
+                    MyOutStr("\r\n");
+                }
+                DosFreeSeg((__segment)pausData);
+            }
+            else if (rc != ERROR_INTERRUPT)
+            {
+                DosCloseQueue(hQueue);
+                MyApiErrorAndQuit("DosReadQueue", rc);
+            }
+        }
+    }
+}
+
+
+/** Displays version string and quits.   */
+static void ShowVersionAndQuit(void)
+{
+    CHAR szVer[] = "$Rev$\r\n";
+    USHORT usIgnored;
+    DosWrite(g_hStdOut, szVer, sizeof(szVer) - 1, &usIgnored);
+    DosExit(EXIT_PROCESS, 0);
+}
+
+
+/** Displays usage info and quits.   */
 static void ShowUsageAndQuit(void)
 {
     static char s_szHelp[] =
-        "Os2Util.exe is tiny helper utility that implements TEE'ing to the VBox release log,\r\n"
-        "files and shows the actual exit code of a program.  Standard error and output will\r\n"
-        "be merged into one for simplicity reasons.\r\n"
+        VBOX_PRODUCT " OS/2 Unattended Helper Version " VBOX_VERSION_STRING "\r\n"
+        "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\r\n"
         "\r\n"
-        "usage: Os2Util.exe [-a|--append] [-f<filename>|--tee-to-file <filename>] \\\r\n"
-        "                   [-b|--tee-to-backdoor] -- <prog> [args]\r\n"
-        "   or  Os2Util.exe <-w<msg>|--write-backdoor <msg>> \r\n";
+        "Os2Util.exe is tiny helper utility that implements TEE'ing to the VBox release\r\n"
+        "log, files and shows the actual exit code of a program.  Standard error and\r\n"
+        "output will be merged into one for simplicity reasons.\r\n"
+        "\r\n"
+        "Usage: Os2Util.exe [-a|--append] [-f<filename>|--tee-to-file <filename>] \\\r\n"
+        "                   [-b|--tee-to-backdoor] [-z<exit>|--as-zero <exit> [..]] \\\r\n"
+        "                   -- <prog> [args]\r\n"
+        "   or  Os2Util.exe <-w<msg>|--write-backdoor <msg>>\r\n"
+        "\r\n"
+        "Note! Does not supported any kind of quoting before the child arguments.\r\n"
+        ;
     USHORT usIgnored;
-    DosWrite(g_hStdErr, s_szHelp, sizeof(s_szHelp) - 1, &usIgnored);
+    DosWrite(g_hStdOut, s_szHelp, sizeof(s_szHelp) - 1, &usIgnored);
     DosExit(EXIT_PROCESS, 0);
 }
@@ -262,8 +398,7 @@
     if (*psz == '\0')
     {
-        USHORT usIgnored;
-        DosWrite(g_hStdErr, RT_STR_TUPLE("Os2Util: syntax error: Option '"), &usIgnored);
-        DosWrite(g_hStdErr, pszOption, MyStrLen(pszOption), &usIgnored);
-        DosWrite(g_hStdErr, RT_STR_TUPLE("' takes a value\r\n"), &usIgnored);
+        MyOutStr("Os2Util: syntax error: Option '");
+        MyOutStr(pszOption);
+        MyOutStr("' takes a value\r\n");
         DosExit(EXIT_PROCESS, 2);
     }
@@ -275,4 +410,81 @@
     if (ch != '\0')
         *psz++ = '\0';
+    return psz;
+}
+
+
+/**
+ * Gets the an numeric option value.
+ */
+static PSZ MyGetOptNum(PSZ psz, PSZ pszOption, PUSHORT puValue)
+{
+    PSZ    pszError = NULL;
+    PSZ    pszValueStart = NULL;
+    PSZ    pszValue;
+    CHAR   ch;
+    USHORT uValue;
+    psz = MyGetOptValue(psz, pszOption, &pszValueStart);
+
+    pszValue = pszValueStart;
+    uValue   = 0;
+    if (pszValue[0] == '0' && ((ch = pszValue[1]) == 'x' || ch == 'X'))
+    {
+        pszValue += 2;
+        while ((ch = *pszValue++) != '\0')
+        {
+            BYTE bDigit;
+            if (ch <= '9' && ch >= '0')
+                bDigit = ch - '0';
+            else if (ch <= 'f' && ch >= 'a')
+                bDigit = ch - 'a' + 10;
+            else if (ch <= 'F' && ch >= 'A')
+                bDigit = ch - 'A' + 10;
+            else
+            {
+                pszError = "': invalid hex value\r\n";
+                break;
+            }
+            if (uValue >> 12)
+            {
+                pszError = "': hex value out of range\r\n";
+                break;
+            }
+            uValue <<= 4;
+            uValue |= bDigit;
+        }
+    }
+    else
+    {
+        while ((ch = *pszValue++) != '\0')
+        {
+            BYTE bDigit;
+            if (ch <= '9' && ch >= '0')
+                bDigit = ch - '0';
+            else
+            {
+                pszError = "': invalid decimal value\r\n";
+                break;
+            }
+            if (uValue * 10 / 10 != uValue)
+            {
+                pszError = "': decimal value out of range\r\n";
+                break;
+            }
+            uValue *= 10;
+            uValue += bDigit;
+        }
+    }
+
+    if (pszError)
+    {
+        MyOutStr("Os2Util: syntax error: Option '");
+        MyOutStr(pszOption);
+        MyOutStr("' with value '");
+        MyOutStr(pszValueStart);
+        MyOutStr(pszError);
+        DosExit(EXIT_PROCESS, 2);
+    }
+
+    *puValue = uValue;
     return psz;
 }
@@ -326,4 +538,13 @@
     RESULTCODES ResultCodes    = { 0xffff, 0xffff };
     CHAR        szBuf[512];
+    CHAR        szExeFull[CCHMAXPATH];
+    PSZ         pszExe;
+    USHORT      uExeType;
+    USHORT      idSession      = 0;
+    PID         pidChild       = 0;
+    HQUEUE      hQueue         = ~(HQUEUE)0;
+    CHAR        szQueueName[64];
+    unsigned    cAsZero;
+    USHORT      auAsZero[16];
 
     /*
@@ -359,4 +580,11 @@
                 if (ch == 'a' && MyMatchLongOption(&psz, RT_STR_TUPLE("append")))
                     fAppend = TRUE;
+                else if (ch == 'a' && MyMatchLongOption(&psz, RT_STR_TUPLE("as-zero")))
+                {
+                    if (cAsZero > RT_ELEMENTS(auAsZero))
+                        MySyntaxErrorAndQuit("Too many --as-zero/-z options");
+                    psz = MyGetOptNum(psz + 1, "--as-zero", &auAsZero[cAsZero]);
+                    cAsZero++;
+                }
                 else if (ch == 'h' && MyMatchLongOption(&psz, RT_STR_TUPLE("help")))
                     ShowUsageAndQuit();
@@ -365,4 +593,6 @@
                 else if (ch == 't' && MyMatchLongOption(&psz, RT_STR_TUPLE("tee-to-file")))
                     psz = MyGetOptValue(psz, "--tee-to-file", &pszTeeToFile);
+                else if (ch == 'v' && MyMatchLongOption(&psz, RT_STR_TUPLE("version")))
+                    ShowVersionAndQuit();
                 else if (ch == 'w' && MyMatchLongOption(&psz, RT_STR_TUPLE("write-backdoor")))
                 {
@@ -373,7 +603,7 @@
                 else
                 {
-                    DosWrite(g_hStdErr, RT_STR_TUPLE("Os2util: syntax error: "), &usIgnored);
-                    DosWrite(g_hStdErr, pszOptStart, MyStrLen(pszOptStart), &usIgnored);
-                    DosWrite(g_hStdErr, RT_STR_TUPLE("\r\n"), &usIgnored);
+                    MyOutStr("Os2util: syntax error: ");
+                    MyOutStr(pszOptStart);
+                    MyOutStr("\r\n");
                     DosExit(EXIT_PROCESS, 2);
                 }
@@ -399,16 +629,25 @@
                         DosExit(EXIT_PROCESS, 0);
                     }
+                    else if (ch == 'z')
+                    {
+                        if (cAsZero > RT_ELEMENTS(auAsZero))
+                            MySyntaxErrorAndQuit("Too many --as-zero/-z options");
+                        psz = MyGetOptNum(psz + 1, "-z", &auAsZero[cAsZero]);
+                        cAsZero++;
+                    }
                     else if (ch == '?' || ch == 'h' || ch == 'H')
                         ShowUsageAndQuit();
+                    else if (ch == 'V')
+                        ShowVersionAndQuit();
                     else
                     {
-                        DosWrite(g_hStdErr, RT_STR_TUPLE("Os2util: syntax error: "), &usIgnored);
+                        MyOutStr("Os2util: syntax error: ");
                         if (ch)
                             DosWrite(g_hStdErr, &ch, 1, &usIgnored);
                         else
-                            DosWrite(g_hStdErr, RT_STR_TUPLE("lone dash"), &usIgnored);
-                        DosWrite(g_hStdErr, RT_STR_TUPLE(" ("), &usIgnored);
-                        DosWrite(g_hStdErr, pszOptStart, MyStrLen(pszOptStart), &usIgnored);
-                        DosWrite(g_hStdErr, RT_STR_TUPLE(")\r\n"), &usIgnored);
+                            MyOutStr("lone dash");
+                        MyOutStr(" (");
+                        MyOutStr(pszOptStart);
+                        MyOutStr(")\r\n");
                         DosExit(EXIT_PROCESS, 2);
                     }
@@ -425,5 +664,5 @@
     if (ch == '\0')
     {
-        DosWrite(g_hStdErr, RT_STR_TUPLE("Os2Util: syntax error: No program specified\r\n"), &usIgnored);
+        MyOutStr("Os2Util: syntax error: No program specified\r\n");
         DosExit(EXIT_PROCESS, 2);
     }
@@ -434,4 +673,29 @@
 
     /*
+     * Find the executable and check its type.
+     */
+    if (   pszzNewCmdLine[1] == ':'
+        || MyStrChr(pszzNewCmdLine, '\\')
+        || MyStrChr(pszzNewCmdLine, '/'))
+        pszExe = pszzNewCmdLine;
+    else
+    {
+        rc = DosSearchPath(SEARCH_CUR_DIRECTORY | SEARCH_ENVIRONMENT | SEARCH_IGNORENETERRS, "PATH",
+                           pszzNewCmdLine, szExeFull, sizeof(szExeFull));
+        if (rc != NO_ERROR)
+            MyApiError3AndQuit("DosSearchPath(7, \"PATH\", \"", pszzNewCmdLine, "\",,)", rc);
+        pszExe = &szExeFull[0];
+    }
+
+    /* Perhapse we should use WinQueryProgramType here instead? */
+    rc = DosQAppType(pszExe, &uExeType);
+    if (rc != NO_ERROR)
+        MyApiErrorAndQuit("DosQAppType(pszExe, &uExeType)", rc);
+#ifdef DEBUG
+    MyOutStr("Os2Util: debug: uExeType="); MyOutNum(uExeType); MyOutStr("\r\n");
+#endif
+    /** @todo deal with launching winos2 programs too...   */
+
+    /*
      * Prepare redirection.
      */
@@ -445,5 +709,5 @@
         rc = DosDupHandle(g_hStdErr, &hDup);
         if (rc != NO_ERROR)
-            MyApiErrorAndQuit("DosDupHandle(g_hStdErr, &hDup);", rc);
+            MyApiErrorAndQuit("DosDupHandle(g_hStdErr, &hDup)", rc);
         g_hStdErr = hDup;
         DosSetFHandState(hDup, OPEN_FLAGS_NOINHERIT); /* not strictly necessary, so ignore errors */
@@ -452,5 +716,5 @@
         rc = DosDupHandle(g_hStdOut, &hDup);
         if (rc != NO_ERROR)
-            MyApiErrorAndQuit("DosDupHandle(g_hStdOut, &hDup);", rc);
+            MyApiErrorAndQuit("DosDupHandle(g_hStdOut, &hDup)", rc);
         g_hStdOut = hDup;
         DosSetFHandState(hDup, OPEN_FLAGS_NOINHERIT); /* not strictly necessary, so ignore errors */
@@ -469,10 +733,10 @@
         rc = DosDupHandle(hPipeWrite, &hDup);
         if (rc != NO_ERROR)
-            MyApiErrorAndQuit("DosDupHandle(hPipeWrite, &hDup[=1]);", rc);
+            MyApiErrorAndQuit("DosDupHandle(hPipeWrite, &hDup[=1])", rc);
 
         hDup = 2;
         rc = DosDupHandle(hPipeWrite, &hDup);
         if (rc != NO_ERROR)
-            MyApiErrorAndQuit("DosDupHandle(hPipeWrite, &hDup[=2]);", rc);
+            MyApiErrorAndQuit("DosDupHandle(hPipeWrite, &hDup[=2])", rc);
 
         /* We can close the write end of the pipe as we don't need the original handle any more. */
@@ -484,20 +748,87 @@
      */
     szBuf[0] = '\0';
-    rc = DosExecPgm(szBuf, sizeof(szBuf), hPipeRead == -1 ? EXEC_SYNC : EXEC_ASYNCRESULT,
-                    pszzNewCmdLine, pszzEnv, &ResultCodes, pszzNewCmdLine);
-    if (rc != NO_ERROR)
-    {
-        MyOutStr("Os2Util: error: DosExecPgm failed for \"");
-        MyOutStr(pszzNewCmdLine);
-        MyOutStr("\": ");
-        MyOutNum(rc);
-        if (szBuf[0])
-        {
-            MyOutStr(" ErrObj=");
-            szBuf[sizeof(szBuf) - 1] = '\0';
-            MyOutStr(szBuf);
-        }
-        MyOutStr("\r\n");
-        DosExit(EXIT_PROCESS, 1);
+#define FAPPTYP_TYPE_MASK 7
+    if ((uExeType & FAPPTYP_TYPE_MASK) == PT_WINDOWABLEVIO) /** @todo what if we're in fullscreen ourselves? */
+    {
+        /* For same type programs we can use DosExecPgm: */
+        rc = DosExecPgm(szBuf, sizeof(szBuf), hPipeRead == -1 ? EXEC_SYNC : EXEC_ASYNCRESULT,
+                        pszzNewCmdLine, pszzEnv, &ResultCodes, pszExe);
+        if (rc != NO_ERROR)
+        {
+            MyOutStr("Os2Util: error: DosExecPgm failed for \"");
+            MyOutStr(pszzNewCmdLine);
+            MyOutStr("\": ");
+            MyOutNum(rc);
+            if (szBuf[0])
+            {
+                MyOutStr(" ErrObj=");
+                szBuf[sizeof(szBuf) - 1] = '\0';
+                MyOutStr(szBuf);
+            }
+            MyOutStr("\r\n");
+            DosExit(EXIT_PROCESS, 1);
+        }
+        if (hPipeRead != -1)
+            pidChild = ResultCodes.codeTerminate;
+    }
+    else
+    {
+        /* For different typed programs we have to use DosStartSession, which
+           is a lot more tedious to use. */
+        static const char   s_szQueueBase[] = "\\QUEUES\\OS2_UTIL-";
+        union
+        {
+            STARTDATA       StartData;
+            BYTE            abPadding[sizeof(STARTDATA) + 64];
+            struct
+            {
+                STARTDATA   Core;
+                ULONG       ulReserved;
+                PSZ         pszBuf;
+                USHORT      cbBuf;
+            } s;
+        } u;
+        PIDINFO             PidInfo         = {0, 0, 0};
+
+        /* Create the wait queue first. */
+        DosGetPID(&PidInfo);
+        MyMemCopy(szQueueName, s_szQueueBase, sizeof(s_szQueueBase));
+        MyNumToString(&szQueueName[sizeof(s_szQueueBase) - 1], PidInfo.pid);
+
+        rc = DosCreateQueue(&hQueue, 0 /*FIFO*/, szQueueName);
+        if (rc != NO_ERROR)
+            MyApiError3AndQuit("DosCreateQueue(&hQueue, 0, \"", szQueueName, "\")", rc);
+
+        u.StartData.Length        = sizeof(u.StartData);
+        u.StartData.Related       = 1 /* SSF_RELATED_CHILD */;
+        u.StartData.FgBg          = 0 /* SSF_FGBG_FORE */;
+        u.StartData.TraceOpt      = 0 /* SSF_TRACEOPT_NONE */;
+        u.StartData.PgmTitle      = NULL;
+        u.StartData.PgmName       = pszExe;
+        u.StartData.PgmInputs     = psz; /* just arguments, not exec apparently.*/
+        u.StartData.TermQ         = szQueueName;
+        u.StartData.Environment   = NULL; /* Inherit our env. Note! Using pszzEnv causes it to be freed
+                                                                    and we'll crash reporting the error. */
+        u.StartData.InheritOpt    = 1 /* SSF_INHERTOPT_PARENT */;
+        u.StartData.SessionType   = uExeType & FAPPTYP_TYPE_MASK;
+        if (uExeType & 0x20 /*FAPPTYP_DOS*/)
+            u.StartData.SessionType = 4 /* SSF_TYPE_VDM */;
+        u.StartData.IconFile      = NULL;
+        u.StartData.PgmHandle     = 0;
+        u.StartData.PgmControl    = 0 /* SSF_CONTROL_VISIBLE */;
+        u.StartData.InitXPos      = 0;
+        u.StartData.InitYPos      = 0;
+        u.StartData.InitXSize     = 0;
+        u.StartData.InitYSize     = 0;
+        u.s.ulReserved            = 0;
+        u.s.pszBuf                = NULL;
+        u.s.cbBuf                 = 0;
+
+        rc = DosStartSession(&u.StartData, &idSession, &pidChild);
+        if (rc != NO_ERROR)
+        {
+            DosCloseQueue(hQueue);
+            MyApiError3AndQuit("DosStartSession for \"", pszExe, "\"", rc);
+        }
     }
 
@@ -507,7 +838,4 @@
     if (hPipeRead != -1)
     {
-        /* Save the child pid. */
-        PID const pidChild = ResultCodes.codeTerminate;
-        PID       pidIgnored;
 
         /* Close the write handles or we'll hang in the read loop. */
@@ -517,5 +845,4 @@
         /* Disable hard error popups (file output to unformatted disks). */
         DosError(2 /* only exceptions */);
-
 
         /*
@@ -538,5 +865,5 @@
                 /* Backdoor: */
                 if (fTeeToBackdoor)
-                    VBoxBackdoorPrint(psz, cbRead);
+                    VBoxBackdoorPrint(szBuf, cbRead);
 
                 /* File: */
@@ -560,14 +887,15 @@
 
         DosClose(hPipeRead);
-        rc = DosCwait(DCWA_PROCESS, DCWW_WAIT, &ResultCodes, &pidIgnored, pidChild);
-        if (rc != NO_ERROR)
-        {
-            MyOutStr("Os2Util: error: DosCwait(DCWA_PROCESS,DCWW_WAIT,,,");
-            MyOutNum(pidChild);
-            MyOutStr(") failed: ");
-            MyOutNum(rc);
-            MyOutStr("\r\n");
-        }
-    }
+
+        /*
+         * Wait for the process to complete.
+         */
+        DoWait(pidChild, idSession, hQueue, &ResultCodes);
+    }
+    /*
+     * Must wait for the session completion too.
+     */
+    else if (idSession != 0)
+        DoWait(pidChild, idSession, hQueue, &ResultCodes);
 
     /*
@@ -585,4 +913,19 @@
     MyOutStr("\r\n");
 
+    /* Treat it as zero? */
+    if (ResultCodes.codeTerminate == 0)
+    {
+        unsigned i = cAsZero;
+        while (i-- > 0)
+            if (auAsZero[i] == ResultCodes.codeResult)
+            {
+                MyOutStr("Os2Util: info: treating status as zero\r\n");
+                ResultCodes.codeResult = 0;
+                break;
+            }
+    }
+
+    if (idSession != 0)
+        DosCloseQueue(hQueue);
     for (;;)
         DosExit(EXIT_PROCESS, ResultCodes.codeTerminate == 0 ? ResultCodes.codeResult : 127);
