Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 78097)
+++ /trunk/include/iprt/mangling.h	(revision 78098)
@@ -1600,5 +1600,4 @@
 # define RTPathAbsDup                                   RT_MANGLER(RTPathAbsDup)
 # define RTPathAbsEx                                    RT_MANGLER(RTPathAbsEx)
-# define RTPathAbsExEx                                  RT_MANGLER(RTPathAbsExEx)
 # define RTPathAbsExDup                                 RT_MANGLER(RTPathAbsExDup)
 # define RTPathAppDocs                                  RT_MANGLER(RTPathAppDocs)
Index: /trunk/include/iprt/path.h
===================================================================
--- /trunk/include/iprt/path.h	(revision 78097)
+++ /trunk/include/iprt/path.h	(revision 78098)
@@ -332,22 +332,4 @@
 /**
  * Get the absolute path (no symlinks, no . or .. components), assuming the
- * given base path as the current directory. The resulting path doesn't have
- * to exist.
- *
- * @returns iprt status code.
- * @param   pszBase         The base path to act like a current directory.
- *                          When NULL, the actual cwd is used (i.e. the call
- *                          is equivalent to RTPathAbs(pszPath, ...).
- * @param   pszPath         The path to resolve.
- * @param   pszAbsPath      Where to store the absolute path.
- * @param   cbAbsPath       Size of the buffer.
- *
- * @note    Current implementation is buggy and will remove trailing slashes
- *          that would normally specify a directory.  Don't depend on this.
- */
-RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, char *pszAbsPath, size_t cbAbsPath);
-
-/**
- * Get the absolute path (no symlinks, no . or .. components), assuming the
  * given base path as the current directory.
  *
@@ -369,5 +351,5 @@
  *                          failures.
  */
-RTDECL(int) RTPathAbsExEx(const char *pszBase, const char *pszPath, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath);
+RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath);
 
 /** @name RTPATHABS_F_XXX - Flags for RTPathAbsEx.
Index: /trunk/src/VBox/HostServices/SharedFolders/vbsfpathabs.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedFolders/vbsfpathabs.cpp	(revision 78097)
+++ /trunk/src/VBox/HostServices/SharedFolders/vbsfpathabs.cpp	(revision 78098)
@@ -185,4 +185,4 @@
     /* Fallback for the common paths. */
 
-    return RTPathAbsExEx(pszRoot, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
+    return RTPathAbsEx(pszRoot, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
 }
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 78097)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 78098)
@@ -7260,5 +7260,5 @@
     char szFolder[RTPATH_MAX];
     size_t cbFolder = sizeof(szFolder);
-    int vrc = RTPathAbsExEx(strSettingsDir.c_str(), strPath.c_str(), RTPATH_STR_F_STYLE_HOST, szFolder, &cbFolder);
+    int vrc = RTPathAbsEx(strSettingsDir.c_str(), strPath.c_str(), RTPATH_STR_F_STYLE_HOST, szFolder, &cbFolder);
     if (RT_SUCCESS(vrc))
         aResult = szFolder;
Index: /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 78097)
+++ /trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 78098)
@@ -4014,9 +4014,9 @@
     char szFolder[RTPATH_MAX];
     size_t cbFolder = sizeof(szFolder);
-    int vrc = RTPathAbsExEx(m->strHomeDir.c_str(),
-                            strPath.c_str(),
-                            RTPATH_STR_F_STYLE_HOST,
-                            szFolder,
-                            &cbFolder);
+    int vrc = RTPathAbsEx(m->strHomeDir.c_str(),
+                          strPath.c_str(),
+                          RTPATH_STR_F_STYLE_HOST,
+                          szFolder,
+                          &cbFolder);
     if (RT_SUCCESS(vrc))
         aResult = szFolder;
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 78097)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 78098)
@@ -512,5 +512,4 @@
 	common/path/RTPathAbsEx.cpp \
 	common/path/RTPathAbsExDup.cpp \
-	common/path/RTPathAbsExEx.cpp \
 	common/path/RTPathAppend.cpp \
 	common/path/RTPathAppendEx.cpp \
@@ -827,5 +826,4 @@
 	generic/RTMpGetCurFrequency-generic.cpp \
 	generic/RTMpGetMaxFrequency-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTRandAdvCreateSystemFaster-generic.cpp \
 	generic/RTRandAdvCreateSystemTruer-generic.cpp \
@@ -917,5 +915,4 @@
 	generic/RTFileMove-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTProcDaemonize-generic.cpp \
@@ -1024,5 +1021,4 @@
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTProcDaemonize-generic.cpp \
@@ -1106,5 +1102,4 @@
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTProcDaemonize-generic.cpp \
@@ -1192,5 +1187,4 @@
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTSemEventMultiWait-2-ex-generic.cpp \
@@ -1275,5 +1269,4 @@
 	generic/RTFileMove-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTSemEventMultiWait-2-ex-generic.cpp \
 	generic/RTSemEventMultiWaitNoResume-2-ex-generic.cpp \
@@ -1357,5 +1350,4 @@
 	generic/RTFileMove-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTProcDaemonize-generic.cpp \
@@ -1454,5 +1446,4 @@
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTProcDaemonize-generic.cpp \
@@ -1707,5 +1698,4 @@
 	common/path/RTPathAbsEx.cpp \
 	common/path/RTPathAbsExDup.cpp \
-	common/path/RTPathAbsExEx.cpp \
 	common/path/RTPathAppend.cpp \
 	common/path/RTPathAppendEx.cpp \
@@ -1888,5 +1878,4 @@
 	generic/RTFileExists-generic.cpp \
 	generic/RTFileSetAllocationSize-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTRandAdvCreateSystemFaster-generic.cpp \
 	generic/RTRandAdvCreateSystemTruer-generic.cpp \
@@ -1957,5 +1946,4 @@
 	generic/RTFileSetAllocationSize-generic.cpp \
 	generic/RTLogWriteDebugger-generic.cpp \
-	generic/RTPathAbs-generic.cpp \
 	generic/RTPathGetCurrentOnDrive-generic.cpp \
 	generic/RTRandAdvCreateSystemFaster-generic.cpp \
@@ -2720,5 +2708,4 @@
 	common/path/RTPathAbsEx.cpp \
 	common/path/RTPathAbsExDup.cpp \
-	common/path/RTPathAbsExEx.cpp \
 	common/path/RTPathAppend.cpp \
 	common/path/RTPathAppendEx.cpp \
Index: /trunk/src/VBox/Runtime/common/path/RTPathAbsEx.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/path/RTPathAbsEx.cpp	(revision 78097)
+++ /trunk/src/VBox/Runtime/common/path/RTPathAbsEx.cpp	(revision 78098)
@@ -1,9 +1,9 @@
 /* $Id$ */
 /** @file
- * IPRT - RTPathAbsEx
+ * IPRT - RTPathAbsEx and RTPathAbs.
  */
 
 /*
- * Copyright (C) 2006-2019 Oracle Corporation
+ * Copyright (C) 2019 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -31,5 +31,8 @@
 #include "internal/iprt.h"
 #include <iprt/path.h>
+
 #include <iprt/err.h>
+#include <iprt/ctype.h>
+#include <iprt/mem.h>
 #include <iprt/param.h>
 #include <iprt/string.h>
@@ -39,70 +42,620 @@
 
 /**
- * Get the absolute path (no symlinks, no . or .. components), assuming the
- * given base path as the current directory. The resulting path doesn't have
- * to exist.
+ * Ensures that the drive letter is capitalized (prereq: RTPATH_PROP_VOLUME).
+ */
+DECLINLINE(void) rtPathAbsExUpperCaseDriveLetter(char *pszAbsPath)
+{
+    AssertReturnVoid(pszAbsPath[1] == ':');
+    char ch = *pszAbsPath;
+    AssertReturnVoid(RT_C_IS_ALPHA(ch));
+    *pszAbsPath = RT_C_TO_UPPER(ch);
+}
+
+
+/**
+ * Common worker for relative paths.
  *
- * @returns iprt status code.
- * @param   pszBase         The base path to act like a current directory.
- *                          When NULL, the actual cwd is used (i.e. the call
- *                          is equivalent to RTPathAbs(pszPath, ...).
- * @param   pszPath         The path to resolve.
- * @param   pszAbsPath      Where to store the absolute path.
- * @param   cbAbsPath       Size of the buffer.
- */
-RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
-{
-#if 0
-    if (    pszBase
-        &&  pszPath
-        &&  !rtPathVolumeSpecLen(pszPath)
-       )
-    {
-# if defined(RT_OS_WINDOWS)
-        /* The format for very long paths is not supported. */
-        if (    RTPATH_IS_SLASH(pszBase[0])
-            &&  RTPATH_IS_SLASH(pszBase[1])
-            &&  pszBase[2] == '?'
-            &&  RTPATH_IS_SLASH(pszBase[3])
-           )
-            return VERR_INVALID_NAME;
-# endif
-
-        /** @todo there are a couple of things which isn't 100% correct, although the
-         * current code will have to do for now, no time to fix.
-         *
-         * 1) On Windows & OS/2 we confuse '/' with an abspath spec and will
-         *    not necessarily resolve it on the right drive.
-         * 2) A trailing slash in the base might cause UNC names to be created.
+ * Uses RTPATHABS_F_STOP_AT_BASE for RTPATHABS_F_STOP_AT_CWD.
+ */
+static int rtPathAbsExWithCwdOrBaseCommon(const char *pszBase, size_t cchBaseInPlace, PRTPATHPARSED pBaseParsed,
+                                          const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags,
+                                          char *pszAbsPath, size_t *pcbAbsPath)
+{
+    AssertReturn(pBaseParsed->cComps > 0, VERR_INVALID_PARAMETER);
+
+    /*
+     * Clean up the base path first if necessary.
+     *
+     * Note! UNC tries to preserve the first two elements in the base path,
+     *       unless it's a \\.\ or \\?\ prefix.
+     */
+    uint32_t const iBaseStop = (pBaseParsed->fProps & (RTPATH_PROP_UNC | RTPATH_PROP_SPECIAL_UNC)) != RTPATH_PROP_UNC
+                            || pBaseParsed->cComps < 2 ? 0 : 1;
+    uint32_t       iBaseLast = iBaseStop;
+    if (pBaseParsed->fProps & (RTPATH_PROP_DOT_REFS | RTPATH_PROP_DOTDOT_REFS))
+    {
+        uint32_t const cComps = pBaseParsed->cComps;
+        uint32_t       i      = iBaseStop + 1;
+        while (i < cComps)
+        {
+            uint32_t const cchComp = pBaseParsed->aComps[i].cch;
+            if (   cchComp > 2
+                || pszPath[pBaseParsed->aComps[i].off] != '.'
+                || (cchComp == 2 && pszPath[pBaseParsed->aComps[i].off + 1] != '.') )
+                iBaseLast = i;
+            else
+            {
+                Assert(cchComp == 1 || cchComp == 2);
+                pBaseParsed->aComps[i].cch = 0;
+                if (cchComp == 2)
+                {
+                    while (iBaseLast > 0 && pBaseParsed->aComps[iBaseLast].cch == 0)
+                        iBaseLast--;
+                    if (iBaseLast > iBaseStop)
+                    {
+                        Assert(pBaseParsed->aComps[iBaseLast].cch != 0);
+                        pBaseParsed->aComps[iBaseLast].cch = 0;
+                        iBaseLast--;
+                    }
+                }
+            }
+            i++;
+        }
+        Assert(iBaseLast < cComps);
+    }
+    else
+        iBaseLast = pBaseParsed->cComps - 1;
+
+    /*
+     * Clean up the path next if needed.
+     */
+    int32_t iLast = -1; /* Is signed here! */
+    if (pParsed->fProps & (RTPATH_PROP_DOT_REFS | RTPATH_PROP_DOTDOT_REFS))
+    {
+        uint32_t const cComps = pParsed->cComps;
+        uint32_t       i      = 0;
+
+        /* If we have a volume specifier, take it from the base path. */
+        if (pParsed->fProps & RTPATH_PROP_VOLUME)
+            pParsed->aComps[i++].cch = 0;
+
+        while (i < cComps)
+        {
+            uint32_t const cchComp = pParsed->aComps[i].cch;
+            if (   cchComp > 2
+                || pszPath[pParsed->aComps[i].off] != '.'
+                || (cchComp == 2 && pszPath[pParsed->aComps[i].off + 1] != '.') )
+                iLast = i;
+            else
+            {
+                Assert(cchComp == 1 || cchComp == 2);
+                pParsed->aComps[i].cch = 0;
+                if (cchComp == 2)
+                {
+                    while (iLast >= 0 && pParsed->aComps[iLast].cch == 0)
+                        iLast--;
+                    if (iLast >= 0)
+                    {
+                        Assert(pParsed->aComps[iLast].cch != 0);
+                        pParsed->aComps[iLast].cch = 0;
+                        iLast--;
+                    }
+                    else if (   iBaseLast > iBaseStop
+                             && !(fFlags & RTPATHABS_F_STOP_AT_BASE))
+                    {
+                        while (iBaseLast > iBaseStop && pBaseParsed->aComps[iBaseLast].cch == 0)
+                            iBaseLast--;
+                        if (iBaseLast > iBaseStop)
+                        {
+                            Assert(pBaseParsed->aComps[iBaseLast].cch != 0);
+                            pBaseParsed->aComps[iBaseLast].cch = 0;
+                            iBaseLast--;
+                        }
+                    }
+                }
+            }
+            i++;
+        }
+        Assert(iLast < (int32_t)cComps);
+    }
+    else
+    {
+        /* If we have a volume specifier, take it from the base path. */
+        iLast = pParsed->cComps - 1;
+        if (pParsed->fProps & RTPATH_PROP_VOLUME)
+        {
+            pParsed->aComps[0].cch = 0;
+            if (iLast == 0)
+                iLast = -1;
+        }
+    }
+
+    /*
+     * Do we need a trailing slash in the base?
+     * If nothing is taken from pszPath, preserve its trailing slash,
+     * otherwise make sure there is a slash for joining the two.
+     */
+    Assert(!(pParsed->fProps & RTPATH_PROP_ROOT_SLASH));
+    if (pBaseParsed->cComps == 1)
+    {
+        AssertReturn(pBaseParsed->fProps & RTPATH_PROP_ROOT_SLASH, VERR_PATH_DOES_NOT_START_WITH_ROOT);
+        Assert(!(pBaseParsed->fProps & RTPATH_PROP_DIR_SLASH));
+    }
+    else
+    {
+        Assert(pBaseParsed->cComps > 1);
+        if (iLast >= 0 || (pParsed->fProps & RTPATH_PROP_DIR_SLASH))
+            pBaseParsed->fProps |= RTPATH_PROP_DIR_SLASH;
+        else
+            pBaseParsed->fProps &= ~RTPATH_PROP_DIR_SLASH;
+    }
+
+    /*
+     * Combine the two.  RTPathParsedReassemble can handle in place stuff, as
+     * long as the path doesn't grow.
+     */
+    int rc = RTPathParsedReassemble(pszBase, pBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, *pcbAbsPath);
+    if (RT_SUCCESS(rc))
+    {
+        if (pBaseParsed->fProps & RTPATH_PROP_VOLUME)
+            rtPathAbsExUpperCaseDriveLetter(pszAbsPath);
+
+        cchBaseInPlace = pBaseParsed->cchPath;
+        Assert(cchBaseInPlace == strlen(pszAbsPath));
+        if (iLast >= 0)
+        {
+            rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK,
+                                        &pszAbsPath[cchBaseInPlace], *pcbAbsPath - cchBaseInPlace);
+            *pcbAbsPath = cchBaseInPlace + pParsed->cchPath;
+            if (RT_SUCCESS(rc))
+                Assert(*pcbAbsPath == strlen(pszAbsPath));
+        }
+        else
+            *pcbAbsPath = cchBaseInPlace;
+    }
+    else if (rc == VERR_BUFFER_OVERFLOW)
+    {
+        if (iLast >= 0)
+        {
+            RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
+            *pcbAbsPath = pBaseParsed->cchPath + pParsed->cchPath;
+        }
+        else
+            *pcbAbsPath = pBaseParsed->cchPath;
+    }
+
+    return rc;
+}
+
+
+/**
+ * Handles the no-root-path scenario where we do CWD prefixing.
+ */
+static int rtPathAbsExWithCwd(const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
+{
+    /*
+     * Get the current directory and place it in the output buffer.
+     */
+    size_t cchInPlace;
+    size_t cbCwd      = *pcbAbsPath;
+    char  *pszCwdFree = NULL;
+    char  *pszCwd     = pszAbsPath;
+    int    rc;
+    if (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
+        || (pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH)) != RTPATH_PROP_VOLUME )
+        rc = RTPathGetCurrent(pszCwd, cbCwd);
+    else
+        rc = RTPathGetCurrentOnDrive(pszPath[0], pszCwd, cbCwd);
+    if (RT_SUCCESS(rc))
+        cchInPlace = strlen(pszCwd);
+    else if (rc == VERR_BUFFER_OVERFLOW)
+    {
+        /* Allocate a big temporary buffer so we can return the correct length
+           (the destination buffer might even be big enough if pszPath includes
+           sufficient '..' entries). */
+        cchInPlace = 0;
+        cbCwd      = RT_MAX(cbCwd * 4, RTPATH_BIG_MAX);
+        pszCwdFree = pszCwd = (char *)RTMemTmpAlloc(cbCwd);
+        if (pszCwdFree)
+        {
+            if (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
+                || (pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH)) != RTPATH_PROP_VOLUME )
+                rc = RTPathGetCurrent(pszCwd, cbCwd);
+            else
+                rc = RTPathGetCurrentOnDrive(pszPath[0], pszCwd, cbCwd);
+            if (RT_FAILURE(rc))
+            {
+                if (rc == VERR_BUFFER_OVERFLOW)
+                    rc = VERR_FILENAME_TOO_LONG;
+                RTMemTmpFree(pszCwdFree);
+                return rc;
+            }
+        }
+        else
+        {
+            *pcbAbsPath = cbCwd + 1 + pParsed->cchPath + 1;
+            return rc;
+        }
+    }
+    else
+        return rc;
+
+    /*
+     * Parse the path.
+     */
+    union
+    {
+        RTPATHPARSED Parsed;
+        uint8_t      abPadding[1024];
+    } uCwd;
+    PRTPATHPARSED pCwdParsedFree = NULL;
+    PRTPATHPARSED pCwdParsed     = &uCwd.Parsed;
+    size_t        cbCwdParsed    = sizeof(uCwd);
+    rc = RTPathParse(pszCwd, pCwdParsed, cbCwdParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else if (rc == VERR_BUFFER_OVERFLOW)
+    {
+        cbCwdParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pCwdParsed->cComps + 2]);
+        pCwdParsedFree = pCwdParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbCwdParsed);
+        AssertReturnStmt(pCwdParsed, RTMemTmpFree(pszCwdFree), VERR_NO_TMP_MEMORY);
+        rc = RTPathParse(pszCwd, pCwdParsed, cbCwdParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+        AssertRCReturnStmt(rc, RTMemTmpFree(pCwdParsedFree); RTMemTmpFree(pszCwdFree), rc);
+    }
+    else
+        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
+
+    /*
+     * Join paths with the base-path code.
+     */
+    if (fFlags & RTPATHABS_F_STOP_AT_CWD)
+        fFlags |= RTPATHABS_F_STOP_AT_BASE;
+    else
+        fFlags &= ~RTPATHABS_F_STOP_AT_BASE;
+    rc = rtPathAbsExWithCwdOrBaseCommon(pszCwd, cchInPlace, pCwdParsed, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+    if (pCwdParsedFree)
+        RTMemTmpFree(pCwdParsedFree);
+    if (pszCwdFree)
+        RTMemTmpFree(pszCwdFree);
+    return rc;
+}
+
+
+/**
+ * Handles the no-root-path scenario where we've got a base path.
+ */
+static int rtPathAbsExWithBase(const char *pszBase, const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags,
+                               char *pszAbsPath, size_t *pcbAbsPath)
+{
+    /*
+     * Parse the base path.
+     */
+    union
+    {
+        RTPATHPARSED Parsed;
+        uint8_t      abPadding[1024];
+    } uBase;
+    PRTPATHPARSED pBaseParsedFree = NULL;
+    PRTPATHPARSED pBaseParsed     = &uBase.Parsed;
+    size_t        cbBaseParsed    = sizeof(uBase);
+    int rc = RTPathParse(pszBase, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else if (rc == VERR_BUFFER_OVERFLOW)
+    {
+        cbBaseParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pBaseParsed->cComps + 2]);
+        pBaseParsedFree = pBaseParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbBaseParsed);
+        AssertReturn(pBaseParsed, VERR_NO_TMP_MEMORY);
+        rc = RTPathParse(pszBase, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+        AssertRCReturnStmt(rc, RTMemTmpFree(pBaseParsedFree), rc);
+    }
+    else
+        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
+
+    /*
+     * If the base path isn't absolute, we need to deal with that.
+     */
+    size_t cchInPlace = 0;
+    if ((pBaseParsed->fProps & (RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS)) == RTPATH_PROP_ABSOLUTE)
+    { /* likely */ }
+    else
+    {
+        cchInPlace = *pcbAbsPath;
+        rc = RTPathAbsEx(NULL, pszBase, fFlags, pszAbsPath, &cchInPlace);
+        if (RT_SUCCESS(rc))
+        {
+            Assert(strlen(pszAbsPath) == cchInPlace);
+            Assert(cchInPlace > 0);
+        }
+        else
+        {
+/** @todo Allocate temp buffer like we do for CWD? */
+            /* This is over generious, but don't want to put too much effort into it yet. */
+            if (rc == VERR_BUFFER_OVERFLOW)
+                *pcbAbsPath = cchInPlace + 1 + pParsed->cchPath + 1;
+            return rc;
+        }
+
+        /*
+         * Reparse it.
          */
-        size_t const cchPath = strlen(pszPath);
-        char         szTmpPath[RTPATH_MAX];
-        if (RTPATH_IS_SLASH(pszPath[0]))
-        {
-            /* join the disk name from base and the path (DOS systems only) */
-            size_t const cchVolSpec = rtPathVolumeSpecLen(pszBase);
-            if (cchVolSpec + cchPath + 1 > sizeof(szTmpPath))
-                return VERR_FILENAME_TOO_LONG;
-            memcpy(szTmpPath, pszBase, cchVolSpec);
-            memcpy(&szTmpPath[cchVolSpec], pszPath, cchPath + 1);
+        rc = RTPathParse(pszAbsPath, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+        if (RT_SUCCESS(rc))
+        { /* likely */ }
+        else if (rc == VERR_BUFFER_OVERFLOW)
+        {
+            if (pBaseParsedFree)
+                RTMemTmpFree(pBaseParsedFree);
+            cbBaseParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pBaseParsed->cComps + 2]);
+            pBaseParsedFree = pBaseParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbBaseParsed);
+            AssertReturn(pBaseParsed, VERR_NO_TMP_MEMORY);
+            rc = RTPathParse(pszAbsPath, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+            AssertRCReturnStmt(rc, RTMemTmpFree(pBaseParsedFree), rc);
         }
         else
-        {
-            /* join the base path and the path */
-            size_t const cchBase = strlen(pszBase);
-            if (cchBase + 1 + cchPath + 1 > sizeof(szTmpPath))
-                return VERR_FILENAME_TOO_LONG;
-            memcpy(szTmpPath, pszBase, cchBase);
-            szTmpPath[cchBase] = RTPATH_DELIMITER;
-            memcpy(&szTmpPath[cchBase + 1], pszPath, cchPath + 1);
-        }
-        return RTPathAbs(szTmpPath, pszAbsPath, cbAbsPath);
-    }
-
-    /* Fallback to the non *Ex version */
-    return RTPathAbs(pszPath, pszAbsPath, cbAbsPath);
-#else
-    return RTPathAbsExEx(pszBase, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
-#endif
-}
-
+            AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
+    }
+
+    /*
+     * Join paths with the CWD code.
+     */
+    rc = rtPathAbsExWithCwdOrBaseCommon(cchInPlace ? pszAbsPath : pszBase, cchInPlace, pBaseParsed,
+                                        pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+    if (pBaseParsedFree)
+        RTMemTmpFree(pBaseParsedFree);
+    return rc;
+}
+
+
+/**
+ * Handles the RTPATH_PROP_ROOT_SLASH case.
+ */
+static int rtPathAbsExRootSlash(const char *pszBase, const char *pszPath, PRTPATHPARSED pParsed,
+                                uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
+{
+    /*
+     * Eliminate dot and dot-dot components.
+     * Note! aComp[0] is the root stuff and must never be dropped.
+     */
+    uint32_t const cComps = pParsed->cComps;
+    uint32_t const iStop  = (pParsed->fProps & (RTPATH_PROP_UNC | RTPATH_PROP_SPECIAL_UNC)) != RTPATH_PROP_UNC
+                         || pParsed->cComps < 2 ? 0 : 1;
+    uint32_t       iLast  = iStop;
+    uint32_t       i      = iStop + 1;
+    while (i < cComps)
+    {
+        uint32_t const cchComp = pParsed->aComps[i].cch;
+        if (   cchComp > 2
+            || pszPath[pParsed->aComps[i].off] != '.'
+            || (cchComp == 2 && pszPath[pParsed->aComps[i].off + 1] != '.') )
+            iLast = i;
+        else
+        {
+            Assert(cchComp == 1 || cchComp == 2);
+            pParsed->aComps[i].cch = 0;
+            if (cchComp == 2)
+            {
+                while (iLast > iStop && pParsed->aComps[iLast].cch == 0)
+                    iLast--;
+                if (iLast > iStop)
+                {
+                    Assert(pParsed->aComps[iLast].cch > 0);
+                    pParsed->aComps[iLast].cch = 0;
+                    iLast--;
+                }
+            }
+        }
+        i++;
+    }
+
+    /*
+     * DOS-style: Do we need to supply a drive letter or UNC root?
+     */
+    size_t cchRootPrefix = 0;
+    if (   (fFlags & RTPATH_STR_F_STYLE_DOS)
+        && !(pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_UNC)) )
+    {
+        /* Use the drive/UNC from the base path if we have one and it has such a component: */
+        if (pszBase)
+        {
+            union
+            {
+                RTPATHPARSED    Parsed;
+                uint8_t         abPadding[sizeof(RTPATHPARSED) + sizeof(pParsed->aComps[0]) * 2];
+            } uBase;
+            int rc = RTPathParse(pszBase, &uBase.Parsed, sizeof(uBase), fFlags & RTPATH_STR_F_STYLE_MASK);
+            AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW, ("%Rrc - '%s'\n", rc, pszBase), rc);
+
+            if (uBase.Parsed.fProps & RTPATH_PROP_VOLUME)
+            {
+                /* get the drive letter. */
+                Assert(uBase.Parsed.aComps[0].cch == 2 || uBase.Parsed.aComps[0].cch == 3);
+                cchRootPrefix = RT_MIN(uBase.Parsed.aComps[0].cch, 2);
+                if (cchRootPrefix < *pcbAbsPath)
+                    memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchRootPrefix);
+                else
+                {
+                    rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
+                    Assert(rc == VERR_BUFFER_OVERFLOW);
+
+                    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + 1;
+                    return VERR_BUFFER_OVERFLOW;
+                }
+                rtPathAbsExUpperCaseDriveLetter(pszAbsPath);
+            }
+            else if (uBase.Parsed.fProps & RTPATH_PROP_UNC)
+            {
+                /* Include the share if we've got one. */
+                cchRootPrefix = uBase.Parsed.aComps[0].cch;
+                if (uBase.Parsed.cComps >= 2 && !(uBase.Parsed.fProps & RTPATH_PROP_SPECIAL_UNC))
+                    cchRootPrefix += uBase.Parsed.aComps[1].cch;
+                else if (uBase.Parsed.fProps & RTPATH_PROP_ROOT_SLASH)
+                    cchRootPrefix--;
+                if (cchRootPrefix < *pcbAbsPath)
+                {
+                    if (uBase.Parsed.cComps < 2 || (uBase.Parsed.fProps & RTPATH_PROP_SPECIAL_UNC))
+                        memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchRootPrefix);
+                    else
+                    {
+                        size_t cchFirst = uBase.Parsed.aComps[0].cch;
+                        memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchFirst);
+                        memcpy(&pszAbsPath[cchFirst], &pszBase[uBase.Parsed.aComps[1].off], uBase.Parsed.aComps[1].cch);
+                    }
+                }
+                else
+                {
+                    rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
+                    Assert(rc == VERR_BUFFER_OVERFLOW);
+
+                    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + 1;
+                    return VERR_BUFFER_OVERFLOW;
+                }
+            }
+            else
+                pszBase = NULL;
+        }
+
+        /* Otherwise, query the current drive: */
+        if (!pszBase)
+        {
+            int rc = RTPathGetCurrentDrive(pszAbsPath, *pcbAbsPath);
+            if (RT_SUCCESS(rc))
+                cchRootPrefix = strlen(pszAbsPath);
+            else
+            {
+                if (rc == VERR_BUFFER_OVERFLOW)
+                {
+                    int rc2 = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
+                    Assert(rc2 == VERR_BUFFER_OVERFLOW); RT_NOREF(rc2);
+
+                    char *pszTmp = (char *)RTMemTmpAlloc(RTPATH_BIG_MAX);
+                    if (pszTmp)
+                    {
+                        rc = RTPathGetCurrentDrive(pszTmp, RTPATH_BIG_MAX);
+                        if (RT_SUCCESS(rc))
+                            *pcbAbsPath = strlen(pszTmp) + pParsed->cchPath + 1;
+                        else
+                            *pcbAbsPath = RT_MAX(*pcbAbsPath * 2, (size_t)RTPATH_BIG_MAX * 3 + pParsed->cchPath + 1);
+                        RTMemTmpFree(pszTmp);
+                    }
+                    else
+                        rc = VERR_NO_TMP_MEMORY;
+                }
+                return rc;
+            }
+        }
+    }
+
+    /*
+     * Reassemble the path and return.
+     */
+    int rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK,
+                                    pszAbsPath + cchRootPrefix, *pcbAbsPath - cchRootPrefix);
+    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + (rc == VERR_BUFFER_OVERFLOW);
+    return rc;
+}
+
+
+/**
+ * Handles the RTPATH_PROP_ABSOLUTE case.
+ */
+static int rtPathAbsExAbsolute(const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
+{
+    if (pParsed->fProps & RTPATH_PROP_DOT_REFS)
+    {
+        uint32_t i = pParsed->cComps;
+        while (i-- > 0)
+            if (   pParsed->aComps[i].cch == 1
+                && pszPath[pParsed->aComps[i].off] == '.')
+                pParsed->aComps[i].cch = 0;
+    }
+    int rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, *pcbAbsPath);
+    *pcbAbsPath = pParsed->cchPath + (rc == VERR_BUFFER_OVERFLOW);
+    if (RT_SUCCESS(rc) && (pParsed->fProps & RTPATH_PROP_VOLUME))
+        rtPathAbsExUpperCaseDriveLetter(pszAbsPath);
+    return rc;
+}
+
+
+RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
+{
+    /*
+     * Some input validation.
+     */
+    AssertPtr(pszPath);
+    AssertPtr(pszAbsPath);
+    AssertPtr(pcbAbsPath);
+    AssertReturn(*pszPath != '\0', VERR_PATH_ZERO_LENGTH);
+
+    AssertCompile(RTPATH_STR_F_STYLE_HOST == 0);
+    AssertReturn(   RTPATH_STR_F_IS_VALID(fFlags, RTPATHABS_F_STOP_AT_BASE | RTPATHABS_F_STOP_AT_CWD)
+                 && !(fFlags & RTPATH_STR_F_MIDDLE), VERR_INVALID_FLAGS);
+    if ((fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_HOST)
+        fFlags |= RTPATH_STYLE;
+
+    /*
+     * Parse the path we're to straigthen out.
+     */
+    union
+    {
+        RTPATHPARSED Parsed;
+        uint8_t      abPadding[1024];
+    } uBuf;
+    PRTPATHPARSED pParsedFree = NULL;
+    PRTPATHPARSED pParsed     = &uBuf.Parsed;
+    size_t        cbParsed    = sizeof(uBuf);
+    int rc = RTPathParse(pszPath, pParsed, cbParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+    if (RT_SUCCESS(rc))
+    { /* likely */ }
+    else if (rc == VERR_BUFFER_OVERFLOW)
+    {
+        cbParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pParsed->cComps + 2]);
+        pParsedFree = pParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbParsed);
+        AssertReturn(pParsed, VERR_NO_TMP_MEMORY);
+        rc = RTPathParse(pszPath, pParsed, cbParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
+        AssertRCReturnStmt(rc, RTMemTmpFree(pParsedFree), rc);
+    }
+    else
+        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
+
+    /*
+     * Check if the input is more or less perfect as it is.
+     */
+    if (pParsed->fProps & RTPATH_PROP_ABSOLUTE)
+        rc = rtPathAbsExAbsolute(pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+    /*
+     * What about relative but with a root slash.
+     */
+    else if (pParsed->fProps & RTPATH_PROP_ROOT_SLASH)
+        rc = rtPathAbsExRootSlash(pszBase, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+    /*
+     * Not exactly perfect.  No root slash.
+     *
+     * If we have a base path, we use it unless we're into drive letters and
+     * pszPath refers to a different drive letter.
+     */
+    else if (   pszBase
+             && (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
+                 /** @todo add flag for skipping this and always using the base path? */
+                 || !(pParsed->fProps & RTPATH_PROP_VOLUME)
+                 || (   RT_C_IS_ALPHA(pszBase[0])
+                     && pszBase[1] == ':'
+                     && RT_C_TO_UPPER(pszBase[0]) == RT_C_TO_UPPER(pszPath[0])
+                    )
+                )
+            )
+        rc = rtPathAbsExWithBase(pszBase, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+    else
+        rc = rtPathAbsExWithCwd(pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
+
+    if (pParsedFree)
+        RTMemTmpFree(pParsedFree);
+    return rc;
+}
+
+
+RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
+{
+    return RTPathAbsEx(NULL, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
+}
+
Index: /trunk/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp	(revision 78097)
+++ /trunk/src/VBox/Runtime/common/path/RTPathAbsExDup.cpp	(revision 78098)
@@ -51,5 +51,5 @@
     char szPath[RTPATH_MAX];
     size_t cbPath = sizeof(szPath);
-    int rc = RTPathAbsExEx(pszBase, pszPath, RTPATH_STR_F_STYLE_HOST, szPath, &cbPath);
+    int rc = RTPathAbsEx(pszBase, pszPath, RTPATH_STR_F_STYLE_HOST, szPath, &cbPath);
     if (RT_SUCCESS(rc))
         return RTStrDup(szPath);
@@ -66,5 +66,5 @@
             if (pszAbsPath)
             {
-                rc = RTPathAbsExEx(pszBase, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbPath);
+                rc = RTPathAbsEx(pszBase, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbPath);
                 if (RT_SUCCESS(rc))
                     return pszAbsPath;
Index: unk/src/VBox/Runtime/common/path/RTPathAbsExEx.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/path/RTPathAbsExEx.cpp	(revision 78097)
+++ 	(revision )
@@ -1,656 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - RTPathAbsExEx
- */
-
-/*
- * Copyright (C) 2019 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*********************************************************************************************************************************
-*   Header Files                                                                                                                 *
-*********************************************************************************************************************************/
-#include "internal/iprt.h"
-#include <iprt/path.h>
-
-#include <iprt/err.h>
-#include <iprt/ctype.h>
-#include <iprt/mem.h>
-#include <iprt/param.h>
-#include <iprt/string.h>
-#include "internal/path.h"
-
-
-
-/**
- * Ensures that the drive letter is capitalized (prereq: RTPATH_PROP_VOLUME).
- */
-DECLINLINE(void) rtPathAbsExExUpperCaseDriveLetter(char *pszAbsPath)
-{
-    AssertReturnVoid(pszAbsPath[1] == ':');
-    char ch = *pszAbsPath;
-    AssertReturnVoid(RT_C_IS_ALPHA(ch));
-    *pszAbsPath = RT_C_TO_UPPER(ch);
-}
-
-
-/**
- * Common worker for relative paths.
- *
- * Uses RTPATHABS_F_STOP_AT_BASE for RTPATHABS_F_STOP_AT_CWD.
- */
-static int rtPathAbsExExWithCwdOrBaseCommon(const char *pszBase, size_t cchBaseInPlace, PRTPATHPARSED pBaseParsed,
-                                            const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags,
-                                            char *pszAbsPath, size_t *pcbAbsPath)
-{
-    AssertReturn(pBaseParsed->cComps > 0, VERR_INVALID_PARAMETER);
-
-    /*
-     * Clean up the base path first if necessary.
-     *
-     * Note! UNC tries to preserve the first two elements in the base path,
-     *       unless it's a \\.\ or \\?\ prefix.
-     */
-    uint32_t const iBaseStop = (pBaseParsed->fProps & (RTPATH_PROP_UNC | RTPATH_PROP_SPECIAL_UNC)) != RTPATH_PROP_UNC
-                            || pBaseParsed->cComps < 2 ? 0 : 1;
-    uint32_t       iBaseLast = iBaseStop;
-    if (pBaseParsed->fProps & (RTPATH_PROP_DOT_REFS | RTPATH_PROP_DOTDOT_REFS))
-    {
-        uint32_t const cComps = pBaseParsed->cComps;
-        uint32_t       i      = iBaseStop + 1;
-        while (i < cComps)
-        {
-            uint32_t const cchComp = pBaseParsed->aComps[i].cch;
-            if (   cchComp > 2
-                || pszPath[pBaseParsed->aComps[i].off] != '.'
-                || (cchComp == 2 && pszPath[pBaseParsed->aComps[i].off + 1] != '.') )
-                iBaseLast = i;
-            else
-            {
-                Assert(cchComp == 1 || cchComp == 2);
-                pBaseParsed->aComps[i].cch = 0;
-                if (cchComp == 2)
-                {
-                    while (iBaseLast > 0 && pBaseParsed->aComps[iBaseLast].cch == 0)
-                        iBaseLast--;
-                    if (iBaseLast > iBaseStop)
-                    {
-                        Assert(pBaseParsed->aComps[iBaseLast].cch != 0);
-                        pBaseParsed->aComps[iBaseLast].cch = 0;
-                        iBaseLast--;
-                    }
-                }
-            }
-            i++;
-        }
-        Assert(iBaseLast < cComps);
-    }
-    else
-        iBaseLast = pBaseParsed->cComps - 1;
-
-    /*
-     * Clean up the path next if needed.
-     */
-    int32_t iLast = -1; /* Is signed here! */
-    if (pParsed->fProps & (RTPATH_PROP_DOT_REFS | RTPATH_PROP_DOTDOT_REFS))
-    {
-        uint32_t const cComps = pParsed->cComps;
-        uint32_t       i      = 0;
-
-        /* If we have a volume specifier, take it from the base path. */
-        if (pParsed->fProps & RTPATH_PROP_VOLUME)
-            pParsed->aComps[i++].cch = 0;
-
-        while (i < cComps)
-        {
-            uint32_t const cchComp = pParsed->aComps[i].cch;
-            if (   cchComp > 2
-                || pszPath[pParsed->aComps[i].off] != '.'
-                || (cchComp == 2 && pszPath[pParsed->aComps[i].off + 1] != '.') )
-                iLast = i;
-            else
-            {
-                Assert(cchComp == 1 || cchComp == 2);
-                pParsed->aComps[i].cch = 0;
-                if (cchComp == 2)
-                {
-                    while (iLast >= 0 && pParsed->aComps[iLast].cch == 0)
-                        iLast--;
-                    if (iLast >= 0)
-                    {
-                        Assert(pParsed->aComps[iLast].cch != 0);
-                        pParsed->aComps[iLast].cch = 0;
-                        iLast--;
-                    }
-                    else if (   iBaseLast > iBaseStop
-                             && !(fFlags & RTPATHABS_F_STOP_AT_BASE))
-                    {
-                        while (iBaseLast > iBaseStop && pBaseParsed->aComps[iBaseLast].cch == 0)
-                            iBaseLast--;
-                        if (iBaseLast > iBaseStop)
-                        {
-                            Assert(pBaseParsed->aComps[iBaseLast].cch != 0);
-                            pBaseParsed->aComps[iBaseLast].cch = 0;
-                            iBaseLast--;
-                        }
-                    }
-                }
-            }
-            i++;
-        }
-        Assert(iLast < (int32_t)cComps);
-    }
-    else
-    {
-        /* If we have a volume specifier, take it from the base path. */
-        iLast = pParsed->cComps - 1;
-        if (pParsed->fProps & RTPATH_PROP_VOLUME)
-        {
-            pParsed->aComps[0].cch = 0;
-            if (iLast == 0)
-                iLast = -1;
-        }
-    }
-
-    /*
-     * Do we need a trailing slash in the base?
-     * If nothing is taken from pszPath, preserve its trailing slash,
-     * otherwise make sure there is a slash for joining the two.
-     */
-    Assert(!(pParsed->fProps & RTPATH_PROP_ROOT_SLASH));
-    if (pBaseParsed->cComps == 1)
-    {
-        AssertReturn(pBaseParsed->fProps & RTPATH_PROP_ROOT_SLASH, VERR_PATH_DOES_NOT_START_WITH_ROOT);
-        Assert(!(pBaseParsed->fProps & RTPATH_PROP_DIR_SLASH));
-    }
-    else
-    {
-        Assert(pBaseParsed->cComps > 1);
-        if (iLast >= 0 || (pParsed->fProps & RTPATH_PROP_DIR_SLASH))
-            pBaseParsed->fProps |= RTPATH_PROP_DIR_SLASH;
-        else
-            pBaseParsed->fProps &= ~RTPATH_PROP_DIR_SLASH;
-    }
-
-    /*
-     * Combine the two.  RTPathParsedReassemble can handle in place stuff, as
-     * long as the path doesn't grow.
-     */
-    int rc = RTPathParsedReassemble(pszBase, pBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, *pcbAbsPath);
-    if (RT_SUCCESS(rc))
-    {
-        if (pBaseParsed->fProps & RTPATH_PROP_VOLUME)
-            rtPathAbsExExUpperCaseDriveLetter(pszAbsPath);
-
-        cchBaseInPlace = pBaseParsed->cchPath;
-        Assert(cchBaseInPlace == strlen(pszAbsPath));
-        if (iLast >= 0)
-        {
-            rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK,
-                                        &pszAbsPath[cchBaseInPlace], *pcbAbsPath - cchBaseInPlace);
-            *pcbAbsPath = cchBaseInPlace + pParsed->cchPath;
-            if (RT_SUCCESS(rc))
-                Assert(*pcbAbsPath == strlen(pszAbsPath));
-        }
-        else
-            *pcbAbsPath = cchBaseInPlace;
-    }
-    else if (rc == VERR_BUFFER_OVERFLOW)
-    {
-        if (iLast >= 0)
-        {
-            RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
-            *pcbAbsPath = pBaseParsed->cchPath + pParsed->cchPath;
-        }
-        else
-            *pcbAbsPath = pBaseParsed->cchPath;
-    }
-
-    return rc;
-}
-
-
-/**
- * Handles the no-root-path scenario where we do CWD prefixing.
- */
-static int rtPathAbsExExWithCwd(const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
-{
-    /*
-     * Get the current directory and place it in the output buffer.
-     */
-    size_t cchInPlace;
-    size_t cbCwd      = *pcbAbsPath;
-    char  *pszCwdFree = NULL;
-    char  *pszCwd     = pszAbsPath;
-    int    rc;
-    if (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
-        || (pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH)) != RTPATH_PROP_VOLUME )
-        rc = RTPathGetCurrent(pszCwd, cbCwd);
-    else
-        rc = RTPathGetCurrentOnDrive(pszPath[0], pszCwd, cbCwd);
-    if (RT_SUCCESS(rc))
-        cchInPlace = strlen(pszCwd);
-    else if (rc == VERR_BUFFER_OVERFLOW)
-    {
-        /* Allocate a big temporary buffer so we can return the correct length
-           (the destination buffer might even be big enough if pszPath includes
-           sufficient '..' entries). */
-        cchInPlace = 0;
-        cbCwd      = RT_MAX(cbCwd * 4, RTPATH_BIG_MAX);
-        pszCwdFree = pszCwd = (char *)RTMemTmpAlloc(cbCwd);
-        if (pszCwdFree)
-        {
-            if (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
-                || (pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH)) != RTPATH_PROP_VOLUME )
-                rc = RTPathGetCurrent(pszCwd, cbCwd);
-            else
-                rc = RTPathGetCurrentOnDrive(pszPath[0], pszCwd, cbCwd);
-            if (RT_FAILURE(rc))
-            {
-                if (rc == VERR_BUFFER_OVERFLOW)
-                    rc = VERR_FILENAME_TOO_LONG;
-                RTMemTmpFree(pszCwdFree);
-                return rc;
-            }
-        }
-        else
-        {
-            *pcbAbsPath = cbCwd + 1 + pParsed->cchPath + 1;
-            return rc;
-        }
-    }
-    else
-        return rc;
-
-    /*
-     * Parse the path.
-     */
-    union
-    {
-        RTPATHPARSED Parsed;
-        uint8_t      abPadding[1024];
-    } uCwd;
-    PRTPATHPARSED pCwdParsedFree = NULL;
-    PRTPATHPARSED pCwdParsed     = &uCwd.Parsed;
-    size_t        cbCwdParsed    = sizeof(uCwd);
-    rc = RTPathParse(pszCwd, pCwdParsed, cbCwdParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-    if (RT_SUCCESS(rc))
-    { /* likely */ }
-    else if (rc == VERR_BUFFER_OVERFLOW)
-    {
-        cbCwdParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pCwdParsed->cComps + 2]);
-        pCwdParsedFree = pCwdParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbCwdParsed);
-        AssertReturnStmt(pCwdParsed, RTMemTmpFree(pszCwdFree), VERR_NO_TMP_MEMORY);
-        rc = RTPathParse(pszCwd, pCwdParsed, cbCwdParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-        AssertRCReturnStmt(rc, RTMemTmpFree(pCwdParsedFree); RTMemTmpFree(pszCwdFree), rc);
-    }
-    else
-        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
-
-    /*
-     * Join paths with the base-path code.
-     */
-    if (fFlags & RTPATHABS_F_STOP_AT_CWD)
-        fFlags |= RTPATHABS_F_STOP_AT_BASE;
-    else
-        fFlags &= ~RTPATHABS_F_STOP_AT_BASE;
-    rc = rtPathAbsExExWithCwdOrBaseCommon(pszCwd, cchInPlace, pCwdParsed, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-    if (pCwdParsedFree)
-        RTMemTmpFree(pCwdParsedFree);
-    if (pszCwdFree)
-        RTMemTmpFree(pszCwdFree);
-    return rc;
-}
-
-
-/**
- * Handles the no-root-path scenario where we've got a base path.
- */
-static int rtPathAbsExExWithBase(const char *pszBase, const char *pszPath, PRTPATHPARSED pParsed, uint32_t fFlags,
-                                 char *pszAbsPath, size_t *pcbAbsPath)
-{
-    /*
-     * Parse the base path.
-     */
-    union
-    {
-        RTPATHPARSED Parsed;
-        uint8_t      abPadding[1024];
-    } uBase;
-    PRTPATHPARSED pBaseParsedFree = NULL;
-    PRTPATHPARSED pBaseParsed     = &uBase.Parsed;
-    size_t        cbBaseParsed    = sizeof(uBase);
-    int rc = RTPathParse(pszBase, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-    if (RT_SUCCESS(rc))
-    { /* likely */ }
-    else if (rc == VERR_BUFFER_OVERFLOW)
-    {
-        cbBaseParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pBaseParsed->cComps + 2]);
-        pBaseParsedFree = pBaseParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbBaseParsed);
-        AssertReturn(pBaseParsed, VERR_NO_TMP_MEMORY);
-        rc = RTPathParse(pszBase, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-        AssertRCReturnStmt(rc, RTMemTmpFree(pBaseParsedFree), rc);
-    }
-    else
-        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
-
-    /*
-     * If the base path isn't absolute, we need to deal with that.
-     */
-    size_t cchInPlace = 0;
-    if ((pBaseParsed->fProps & (RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS)) == RTPATH_PROP_ABSOLUTE)
-    { /* likely */ }
-    else
-    {
-        cchInPlace = *pcbAbsPath;
-        rc = RTPathAbsExEx(NULL, pszBase, fFlags, pszAbsPath, &cchInPlace);
-        if (RT_SUCCESS(rc))
-        {
-            Assert(strlen(pszAbsPath) == cchInPlace);
-            Assert(cchInPlace > 0);
-        }
-        else
-        {
-/** @todo Allocate temp buffer like we do for CWD? */
-            /* This is over generious, but don't want to put too much effort into it yet. */
-            if (rc == VERR_BUFFER_OVERFLOW)
-                *pcbAbsPath = cchInPlace + 1 + pParsed->cchPath + 1;
-            return rc;
-        }
-
-        /*
-         * Reparse it.
-         */
-        rc = RTPathParse(pszAbsPath, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-        if (RT_SUCCESS(rc))
-        { /* likely */ }
-        else if (rc == VERR_BUFFER_OVERFLOW)
-        {
-            if (pBaseParsedFree)
-                RTMemTmpFree(pBaseParsedFree);
-            cbBaseParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pBaseParsed->cComps + 2]);
-            pBaseParsedFree = pBaseParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbBaseParsed);
-            AssertReturn(pBaseParsed, VERR_NO_TMP_MEMORY);
-            rc = RTPathParse(pszAbsPath, pBaseParsed, cbBaseParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-            AssertRCReturnStmt(rc, RTMemTmpFree(pBaseParsedFree), rc);
-        }
-        else
-            AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
-    }
-
-    /*
-     * Join paths with the CWD code.
-     */
-    rc = rtPathAbsExExWithCwdOrBaseCommon(cchInPlace ? pszAbsPath : pszBase, cchInPlace, pBaseParsed,
-                                          pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-    if (pBaseParsedFree)
-        RTMemTmpFree(pBaseParsedFree);
-    return rc;
-}
-
-
-/**
- * Handles the RTPATH_PROP_ROOT_SLASH case.
- */
-static int rtPathAbsExExRootSlash(const char *pszBase, const char *pszPath, PRTPATHPARSED pParsed,
-                                  uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
-{
-    /*
-     * Eliminate dot and dot-dot components.
-     * Note! aComp[0] is the root stuff and must never be dropped.
-     */
-    uint32_t const cComps = pParsed->cComps;
-    uint32_t const iStop  = (pParsed->fProps & (RTPATH_PROP_UNC | RTPATH_PROP_SPECIAL_UNC)) != RTPATH_PROP_UNC
-                         || pParsed->cComps < 2 ? 0 : 1;
-    uint32_t       iLast  = iStop;
-    uint32_t       i      = iStop + 1;
-    while (i < cComps)
-    {
-        uint32_t const cchComp = pParsed->aComps[i].cch;
-        if (   cchComp > 2
-            || pszPath[pParsed->aComps[i].off] != '.'
-            || (cchComp == 2 && pszPath[pParsed->aComps[i].off + 1] != '.') )
-            iLast = i;
-        else
-        {
-            Assert(cchComp == 1 || cchComp == 2);
-            pParsed->aComps[i].cch = 0;
-            if (cchComp == 2)
-            {
-                while (iLast > iStop && pParsed->aComps[iLast].cch == 0)
-                    iLast--;
-                if (iLast > iStop)
-                {
-                    Assert(pParsed->aComps[iLast].cch > 0);
-                    pParsed->aComps[iLast].cch = 0;
-                    iLast--;
-                }
-            }
-        }
-        i++;
-    }
-
-    /*
-     * DOS-style: Do we need to supply a drive letter or UNC root?
-     */
-    size_t cchRootPrefix = 0;
-    if (   (fFlags & RTPATH_STR_F_STYLE_DOS)
-        && !(pParsed->fProps & (RTPATH_PROP_VOLUME | RTPATH_PROP_UNC)) )
-    {
-        /* Use the drive/UNC from the base path if we have one and it has such a component: */
-        if (pszBase)
-        {
-            union
-            {
-                RTPATHPARSED    Parsed;
-                uint8_t         abPadding[sizeof(RTPATHPARSED) + sizeof(pParsed->aComps[0]) * 2];
-            } uBase;
-            int rc = RTPathParse(pszBase, &uBase.Parsed, sizeof(uBase), fFlags & RTPATH_STR_F_STYLE_MASK);
-            AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW, ("%Rrc - '%s'\n", rc, pszBase), rc);
-
-            if (uBase.Parsed.fProps & RTPATH_PROP_VOLUME)
-            {
-                /* get the drive letter. */
-                Assert(uBase.Parsed.aComps[0].cch == 2 || uBase.Parsed.aComps[0].cch == 3);
-                cchRootPrefix = RT_MIN(uBase.Parsed.aComps[0].cch, 2);
-                if (cchRootPrefix < *pcbAbsPath)
-                    memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchRootPrefix);
-                else
-                {
-                    rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
-                    Assert(rc == VERR_BUFFER_OVERFLOW);
-
-                    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + 1;
-                    return VERR_BUFFER_OVERFLOW;
-                }
-                rtPathAbsExExUpperCaseDriveLetter(pszAbsPath);
-            }
-            else if (uBase.Parsed.fProps & RTPATH_PROP_UNC)
-            {
-                /* Include the share if we've got one. */
-                cchRootPrefix = uBase.Parsed.aComps[0].cch;
-                if (uBase.Parsed.cComps >= 2 && !(uBase.Parsed.fProps & RTPATH_PROP_SPECIAL_UNC))
-                    cchRootPrefix += uBase.Parsed.aComps[1].cch;
-                else if (uBase.Parsed.fProps & RTPATH_PROP_ROOT_SLASH)
-                    cchRootPrefix--;
-                if (cchRootPrefix < *pcbAbsPath)
-                {
-                    if (uBase.Parsed.cComps < 2 || (uBase.Parsed.fProps & RTPATH_PROP_SPECIAL_UNC))
-                        memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchRootPrefix);
-                    else
-                    {
-                        size_t cchFirst = uBase.Parsed.aComps[0].cch;
-                        memcpy(pszAbsPath, &pszBase[uBase.Parsed.aComps[0].off], cchFirst);
-                        memcpy(&pszAbsPath[cchFirst], &pszBase[uBase.Parsed.aComps[1].off], uBase.Parsed.aComps[1].cch);
-                    }
-                }
-                else
-                {
-                    rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
-                    Assert(rc == VERR_BUFFER_OVERFLOW);
-
-                    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + 1;
-                    return VERR_BUFFER_OVERFLOW;
-                }
-            }
-            else
-                pszBase = NULL;
-        }
-
-        /* Otherwise, query the current drive: */
-        if (!pszBase)
-        {
-            int rc = RTPathGetCurrentDrive(pszAbsPath, *pcbAbsPath);
-            if (RT_SUCCESS(rc))
-                cchRootPrefix = strlen(pszAbsPath);
-            else
-            {
-                if (rc == VERR_BUFFER_OVERFLOW)
-                {
-                    int rc2 = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, 0);
-                    Assert(rc2 == VERR_BUFFER_OVERFLOW); RT_NOREF(rc2);
-
-                    char *pszTmp = (char *)RTMemTmpAlloc(RTPATH_BIG_MAX);
-                    if (pszTmp)
-                    {
-                        rc = RTPathGetCurrentDrive(pszTmp, RTPATH_BIG_MAX);
-                        if (RT_SUCCESS(rc))
-                            *pcbAbsPath = strlen(pszTmp) + pParsed->cchPath + 1;
-                        else
-                            *pcbAbsPath = RT_MAX(*pcbAbsPath * 2, (size_t)RTPATH_BIG_MAX * 3 + pParsed->cchPath + 1);
-                        RTMemTmpFree(pszTmp);
-                    }
-                    else
-                        rc = VERR_NO_TMP_MEMORY;
-                }
-                return rc;
-            }
-        }
-    }
-
-    /*
-     * Reassemble the path and return.
-     */
-    int rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK,
-                                    pszAbsPath + cchRootPrefix, *pcbAbsPath - cchRootPrefix);
-    *pcbAbsPath = cchRootPrefix + pParsed->cchPath + (rc == VERR_BUFFER_OVERFLOW);
-    return rc;
-}
-
-
-/**
- * Handles the RTPATH_PROP_ABSOLUTE case.
- */
-static int rtPathAbsExExAbsolute(const char *pszPath, PRTPATHPARSED pParsed,
-                                 uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
-{
-    if (pParsed->fProps & RTPATH_PROP_DOT_REFS)
-    {
-        uint32_t i = pParsed->cComps;
-        while (i-- > 0)
-            if (   pParsed->aComps[i].cch == 1
-                && pszPath[pParsed->aComps[i].off] == '.')
-                pParsed->aComps[i].cch = 0;
-    }
-    int rc = RTPathParsedReassemble(pszPath, pParsed, fFlags & RTPATH_STR_F_STYLE_MASK, pszAbsPath, *pcbAbsPath);
-    *pcbAbsPath = pParsed->cchPath + (rc == VERR_BUFFER_OVERFLOW);
-    if (RT_SUCCESS(rc) && (pParsed->fProps & RTPATH_PROP_VOLUME))
-        rtPathAbsExExUpperCaseDriveLetter(pszAbsPath);
-    return rc;
-}
-
-
-RTDECL(int) RTPathAbsExEx(const char *pszBase, const char *pszPath, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath)
-{
-    /*
-     * Some input validation.
-     */
-    AssertPtr(pszPath);
-    AssertPtr(pszAbsPath);
-    AssertPtr(pcbAbsPath);
-    AssertReturn(*pszPath != '\0', VERR_PATH_ZERO_LENGTH);
-
-    AssertCompile(RTPATH_STR_F_STYLE_HOST == 0);
-    AssertReturn(   RTPATH_STR_F_IS_VALID(fFlags, RTPATHABS_F_STOP_AT_BASE | RTPATHABS_F_STOP_AT_CWD)
-                 && !(fFlags & RTPATH_STR_F_MIDDLE), VERR_INVALID_FLAGS);
-    if ((fFlags & RTPATH_STR_F_STYLE_MASK) == RTPATH_STR_F_STYLE_HOST)
-        fFlags |= RTPATH_STYLE;
-
-    /*
-     * Parse the path we're to straigthen out.
-     */
-    union
-    {
-        RTPATHPARSED Parsed;
-        uint8_t      abPadding[1024];
-    } uBuf;
-    PRTPATHPARSED pParsedFree = NULL;
-    PRTPATHPARSED pParsed     = &uBuf.Parsed;
-    size_t        cbParsed    = sizeof(uBuf);
-    int rc = RTPathParse(pszPath, pParsed, cbParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-    if (RT_SUCCESS(rc))
-    { /* likely */ }
-    else if (rc == VERR_BUFFER_OVERFLOW)
-    {
-        cbParsed = RT_UOFFSETOF_DYN(RTPATHPARSED, aComps[pParsed->cComps + 2]);
-        pParsedFree = pParsed = (PRTPATHPARSED)RTMemTmpAlloc(cbParsed);
-        AssertReturn(pParsed, VERR_NO_TMP_MEMORY);
-        rc = RTPathParse(pszPath, pParsed, cbParsed, fFlags & RTPATH_STR_F_STYLE_MASK);
-        AssertRCReturnStmt(rc, RTMemTmpFree(pParsedFree), rc);
-    }
-    else
-        AssertMsgFailedReturn(("rc=%Rrc '%s'\n", rc, pszPath), rc);
-
-    /*
-     * Check if the input is more or less perfect as it is.
-     */
-    if (pParsed->fProps & RTPATH_PROP_ABSOLUTE)
-        rc = rtPathAbsExExAbsolute(pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-    /*
-     * What about relative but with a root slash.
-     */
-    else if (pParsed->fProps & RTPATH_PROP_ROOT_SLASH)
-        rc = rtPathAbsExExRootSlash(pszBase, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-    /*
-     * Not exactly perfect.  No root slash.
-     *
-     * If we have a base path, we use it unless we're into drive letters and
-     * pszPath refers to a different drive letter.
-     */
-    else if (   pszBase
-             && (   !(fFlags & RTPATH_STR_F_STYLE_DOS)
-                 /** @todo add flag for skipping this and always using the base path? */
-                 || !(pParsed->fProps & RTPATH_PROP_VOLUME)
-                 || (   RT_C_IS_ALPHA(pszBase[0])
-                     && pszBase[1] == ':'
-                     && RT_C_TO_UPPER(pszBase[0]) == RT_C_TO_UPPER(pszPath[0])
-                    )
-                )
-            )
-        rc = rtPathAbsExExWithBase(pszBase, pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-    else
-        rc = rtPathAbsExExWithCwd(pszPath, pParsed, fFlags, pszAbsPath, pcbAbsPath);
-
-    if (pParsedFree)
-        RTMemTmpFree(pParsedFree);
-    return rc;
-}
-
Index: unk/src/VBox/Runtime/generic/RTPathAbs-generic.cpp
===================================================================
--- /trunk/src/VBox/Runtime/generic/RTPathAbs-generic.cpp	(revision 78097)
+++ 	(revision )
@@ -1,384 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - RTPathAbs, generic implementation.
- */
-
-/*
- * Copyright (C) 2006-2019 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*********************************************************************************************************************************
-*   Header Files                                                                                                                 *
-*********************************************************************************************************************************/
-#define LOG_GROUP RTLOGGROUP_PATH
-#include <iprt/path.h>
-
-#include <iprt/assert.h>
-#include <iprt/ctype.h>
-#include <iprt/err.h>
-#include <iprt/log.h>
-#include <iprt/string.h>
-#include "internal/path.h"
-#include "internal/fs.h"
-
-#if 0
-
-static char *rtPathSkipRootSpec(char *pszCur)
-{
-#ifdef HAVE_DRIVE
-    if (pszCur[0] && RTPATH_IS_VOLSEP(pszCur[1]) && pszCur[2] == RTPATH_SLASH)
-        pszCur += 3;
-# ifdef HAVE_UNC
-    else if (pszCur[0] == RTPATH_SLASH && pszCur[1] == RTPATH_SLASH)
-    {
-        pszCur += 2;
-        while (*pszCur == RTPATH_SLASH)
-            pszCur++;
-        if (*pszCur)
-        {
-            while (*pszCur != RTPATH_SLASH && *pszCur)
-                pszCur++;
-            if (*pszCur == RTPATH_SLASH)
-            {
-                pszCur++;
-                while (*pszCur != RTPATH_SLASH && *pszCur)
-                    pszCur++;
-                if (*pszCur == RTPATH_SLASH)
-                    pszCur++;
-            }
-        }
-    }
-# endif
-#else
-    if (pszCur[0] == RTPATH_SLASH)
-        pszCur += 1;
-#endif
-    return pszCur;
-}
-
-
-/**
- * Cleans up a path specifier a little bit.
- *
- * This includes removing duplicate slashes, unnecessary single dots, and
- * trailing slashes. Also, replaces all slash characters with RTPATH_SLASH.
- *
- * @returns Length of the cleaned path (in chars).
- * @param   pszPath     The path to cleanup.
- */
-static int fsCleanPath(char *pszPath)
-{
-    char *pszSrc = pszPath;
-    char *pszTrg = pszPath;
-
-    /*
-     * On windows, you either use on or two slashes at the head of a path,
-     * seems like it treats additional slashes as part of the UNC server name.
-     * Just change slashes to RTPATH_SLASH and skip them.
-     */
-    /** @todo check how OS/2 treats unnecessary leading slashes */
-    /*int cchIgnoreLeading = 0;*/
-#ifdef HAVE_UNC
-    if (   RTPATH_IS_SLASH(pszSrc[0])
-        && RTPATH_IS_SLASH(pszSrc[1]))
-    {
-        pszTrg[0] = RTPATH_SLASH;
-        pszTrg[1] = RTPATH_SLASH;
-        pszTrg += 2;
-        pszSrc += 2;
-        /*cchIgnoreLeading = 1;*/
-        while (RTPATH_IS_SLASH(*pszSrc))
-        {
-            /*cchIgnoreLeading++;*/
-            pszSrc++;
-            *pszTrg++ = RTPATH_SLASH;
-        }
-    }
-#endif
-
-    /*
-     * Change slashes to RTPATH_SLASH and remove duplicates.
-     */
-    for (;;)
-    {
-        char ch = *pszSrc++;
-        if (RTPATH_IS_SLASH(ch))
-        {
-            *pszTrg++ = RTPATH_SLASH;
-            for (;;)
-            {
-                do
-                    ch = *pszSrc++;
-                while (RTPATH_IS_SLASH(ch));
-
-                /* Remove '/./' and '/.'. */
-                if (   ch != '.'
-                    || (*pszSrc && !RTPATH_IS_SLASH(*pszSrc)))
-                    break;
-            }
-        }
-        *pszTrg = ch;
-        if (!ch)
-            break;
-        pszTrg++;
-    }
-
-    return pszTrg - pszPath;
-}
-
-
-RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
-{
-    int rc;
-
-    /*
-     * Validation.
-     */
-    AssertPtr(pszAbsPath);
-    AssertPtr(pszPath);
-    if (RT_UNLIKELY(!*pszPath))
-        return VERR_INVALID_PARAMETER; //VERR_INVALID_NAME;
-
-    /*
-     * Make a clean working copy of the input.
-     */
-    size_t cchPath = strlen(pszPath);
-    if (cchPath >= RTPATH_MAX)
-    {
-        LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cbAbsPath, VERR_FILENAME_TOO_LONG));
-        return VERR_FILENAME_TOO_LONG;
-    }
-
-    char szTmpPath[RTPATH_MAX];
-    memcpy(szTmpPath, pszPath, cchPath + 1);
-    size_t cchTmpPath = fsCleanPath(szTmpPath);
-
-    /*
-     * Handle "." specially (fsCleanPath does).
-     */
-    if (szTmpPath[0] == '.')
-    {
-        if (   cchTmpPath == 1
-            || (cchTmpPath == 2 && szTmpPath[1] == RTPATH_SLASH))
-        {
-            rc = RTPathGetCurrent(pszAbsPath, cbAbsPath);
-            if (RT_SUCCESS(rc))
-            {
-                size_t cch = fsCleanPath(pszAbsPath);
-                char  *pszTop = rtPathSkipRootSpec(pszAbsPath);
-#if 1
-                if ((uintptr_t)&pszAbsPath[cch] > (uintptr_t)pszTop && pszAbsPath[cch - 1] == RTPATH_SLASH)
-                    pszAbsPath[cch - 1] = '\0';
-#else
-                if (   cchTmpPath == 2
-                    && (uintptr_t)&pszAbsPath[cch - 1] > (uintptr_t)pszTop && pszAbsPath[cch - 1] != RTPATH_SLASH)
-                {
-                    if (cch + 1 < cbAbsPath)
-                    {
-                        pszAbsPath[cch++] = RTPATH_SLASH;
-                        pszAbsPath[cch] = '\0';
-                    }
-                    else
-                        rc = VERR_BUFFER_OVERFLOW;
-                }
-#endif
-            }
-            return rc;
-        }
-    }
-
-    /*
-     * Do we have an incomplete root spec?  Supply the missing bits.
-     */
-#ifdef HAVE_DRIVE
-    if (   !(szTmpPath[0] && RTPATH_IS_VOLSEP(szTmpPath[1]) && szTmpPath[2] == RTPATH_SLASH)
-# ifdef HAVE_UNC
-        && !(szTmpPath[0] == RTPATH_SLASH && szTmpPath[1] == RTPATH_SLASH)
-# endif
-        )
-#else
-    if (szTmpPath[0] != RTPATH_SLASH)
-#endif
-    {
-        char    szCurDir[RTPATH_MAX];
-        size_t  cchCurDir;
-        int     offApplyAt;
-        bool    fNeedSlash;
-#ifdef HAVE_DRIVE
-        if (szTmpPath[0] && RTPATH_IS_VOLSEP(szTmpPath[1]) && szTmpPath[2] != RTPATH_SLASH)
-        {
-            /*
-             * Relative to drive specific current directory.
-             */
-            rc = RTPathGetCurrentOnDrive(szTmpPath[0], szCurDir, sizeof(szCurDir));
-            fNeedSlash = true;
-            offApplyAt = 2;
-        }
-# ifdef HAVE_UNC
-        else if (szTmpPath[0] == RTPATH_SLASH && szTmpPath[1] != RTPATH_SLASH)
-# else
-        else if (szTmpPath[0] == RTPATH_SLASH)
-# endif
-        {
-            /*
-             * Root of current drive.  This may return a UNC root if we're not
-             * standing on a drive but on a UNC share.
-             */
-            rc = RTPathGetCurrentDrive(szCurDir, sizeof(szCurDir));
-            fNeedSlash = false;
-            offApplyAt = 0;
-        }
-        else
-#endif
-        {
-            /*
-             * Relative to current directory.
-             */
-            rc = RTPathGetCurrent(szCurDir, sizeof(szCurDir));
-            fNeedSlash = true;
-            offApplyAt = 0;
-        }
-        if (RT_SUCCESS(rc))
-        {
-            cchCurDir = fsCleanPath(szCurDir);
-            if (fNeedSlash && cchCurDir > 0 && szCurDir[cchCurDir - 1] == RTPATH_SLASH)
-                fNeedSlash = false;
-
-            if (cchCurDir + fNeedSlash + cchTmpPath - offApplyAt <= RTPATH_MAX)
-            {
-                memmove(szTmpPath + cchCurDir + fNeedSlash, szTmpPath + offApplyAt, cchTmpPath + 1 - offApplyAt);
-                memcpy(szTmpPath, szCurDir, cchCurDir);
-                if (fNeedSlash)
-                    szTmpPath[cchCurDir] = RTPATH_SLASH;
-            }
-            else
-                rc = VERR_FILENAME_TOO_LONG;
-        }
-        if (RT_FAILURE(rc))
-        {
-            LogFlow(("RTPathAbs(%p:{%s}, %p, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath, cbAbsPath, rc));
-            return rc;
-        }
-    }
-
-    /*
-     * Skip past the root spec.
-     */
-    char *pszCur = rtPathSkipRootSpec(szTmpPath);
-    AssertMsgReturn(pszCur != &szTmpPath[0], ("pszCur=%s\n", pszCur), VERR_INTERNAL_ERROR);
-    char * const pszTop = pszCur;
-
-    /*
-     * Get rid of double dot path components by evaluating them.
-     */
-    for (;;)
-    {
-        char const chFirst = pszCur[0];
-        if (   chFirst == '.'
-            && pszCur[1] == '.'
-            && (!pszCur[2] || pszCur[2] == RTPATH_SLASH))
-        {
-            /* rewind to the previous component if any */
-            char *pszPrev = pszCur;
-            if ((uintptr_t)pszPrev > (uintptr_t)pszTop)
-            {
-                pszPrev--;
-                while (   (uintptr_t)pszPrev > (uintptr_t)pszTop
-                       && pszPrev[-1] != RTPATH_SLASH)
-                    pszPrev--;
-            }
-            if (!pszCur[2])
-            {
-                if (pszPrev != pszTop)
-                    pszPrev[-1] = '\0';
-                else
-                    *pszPrev = '\0';
-                break;
-            }
-            Assert(pszPrev[-1] == RTPATH_SLASH);
-            memmove(pszPrev, pszCur + 3, strlen(pszCur + 3) + 1);
-            pszCur = pszPrev - 1;
-        }
-        else if (   chFirst == '.'
-                 && (!pszCur[1] || pszCur[1] == RTPATH_SLASH))
-        {
-            /* remove unnecessary '.' */
-            if (!pszCur[1])
-            {
-                if (pszCur != pszTop)
-                    pszCur[-1] = '\0';
-                else
-                    *pszCur = '\0';
-                break;
-            }
-            memmove(pszCur, pszCur + 2, strlen(pszCur + 2) + 1);
-            continue;
-        }
-        else
-        {
-            /* advance to end of component. */
-            while (*pszCur && *pszCur != RTPATH_SLASH)
-                pszCur++;
-        }
-
-        if (!*pszCur)
-            break;
-
-        /* skip the slash */
-        ++pszCur;
-    }
-
-    cchTmpPath = pszCur - szTmpPath;
-
-#if 1
-    /*
-     * Strip trailing slash if that's what's desired.
-     */
-
-    if ((uintptr_t)&szTmpPath[cchTmpPath] > (uintptr_t)pszTop && szTmpPath[cchTmpPath - 1] == RTPATH_SLASH)
-        szTmpPath[--cchTmpPath] = '\0';
-#endif
-
-    /*
-     * Copy the result to the user buffer.
-     */
-    if (cchTmpPath < cbAbsPath)
-    {
-        memcpy(pszAbsPath, szTmpPath, cchTmpPath + 1);
-        rc = VINF_SUCCESS;
-    }
-    else
-        rc = VERR_BUFFER_OVERFLOW;
-
-    LogFlow(("RTPathAbs(%p:{%s}, %p:{%s}, %d): returns %Rrc\n", pszPath, pszPath, pszAbsPath,
-             RT_SUCCESS(rc) ? pszAbsPath : "<failed>", cbAbsPath, rc));
-    return rc;
-}
-
-#else
-
-RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cbAbsPath)
-{
-    return RTPathAbsExEx(NULL, pszPath, RTPATH_STR_F_STYLE_HOST, pszAbsPath, &cbAbsPath);
-}
-
-#endif
-
Index: /trunk/src/VBox/Runtime/r3/generic/dirrel-r3-generic.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/generic/dirrel-r3-generic.cpp	(revision 78097)
+++ /trunk/src/VBox/Runtime/r3/generic/dirrel-r3-generic.cpp	(revision 78098)
@@ -84,5 +84,5 @@
      * This ASSUMES that pThis->pszPath is an absolute path.
      */
-    int rc = RTPathAbsExEx(pThis->pszPath, pszRelPath, RTPATH_STR_F_STYLE_HOST, pszPathDst, &cbPathDst);
+    int rc = RTPathAbsEx(pThis->pszPath, pszRelPath, RTPATH_STR_F_STYLE_HOST, pszPathDst, &cbPathDst);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp	(revision 78097)
+++ /trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp	(revision 78098)
@@ -95,5 +95,5 @@
      * This ASSUMES that pThis->pszPath is an absolute path.
      */
-    int rc = RTPathAbsExEx(pThis->pszPath, pszRelPath, RTPATH_STR_F_STYLE_HOST, pszPathDst, &cbPathDst);
+    int rc = RTPathAbsEx(pThis->pszPath, pszRelPath, RTPATH_STR_F_STYLE_HOST, pszPathDst, &cbPathDst);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp	(revision 78097)
+++ /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp	(revision 78098)
@@ -267,142 +267,8 @@
 
 
-#if 0
-    /*
-     * RTPathAbsEx
+    /*
+     * RTPathAbsEx.
      */
     RTTestSub(hTest, "RTPathAbsEx");
-    static const struct
-    {
-        const char *pcszInputBase;
-        const char *pcszInputPath;
-        int rc;
-        const char *pcszOutput;
-    }
-    s_aRTPathAbsExTests[] =
-    {
-#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
-    { NULL, "", VERR_INVALID_PARAMETER, NULL },
-    { NULL, ".", VINF_SUCCESS, "%p" },
-    { NULL, "\\", VINF_SUCCESS, "%d\\" },
-    { NULL, "\\..", VINF_SUCCESS, "%d\\" },
-    { NULL, "/absolute/..", VINF_SUCCESS, "%d\\" },
-    { NULL, "/absolute\\\\../..", VINF_SUCCESS, "%d\\" },
-    { NULL, "/absolute//../path\\", VINF_SUCCESS, "%d\\path" },
-    { NULL, "/absolute/../../path", VINF_SUCCESS, "%d\\path" },
-    { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p\\dir\\file.txt" },
-    { NULL, "\\data\\", VINF_SUCCESS, "%d\\data" },
-    { "relative_base/dir\\", "\\from_root", VINF_SUCCESS, "%d\\from_root" },
-    { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p\\relative_base\\dir\\relative_also" },
-#else
-    { NULL, "", VERR_INVALID_PARAMETER, NULL },
-    { NULL, ".", VINF_SUCCESS, "%p" },
-    { NULL, "/", VINF_SUCCESS, "/" },
-    { NULL, "/..", VINF_SUCCESS, "/" },
-    { NULL, "/absolute/..", VINF_SUCCESS, "/" },
-    { NULL, "/absolute\\\\../..", VINF_SUCCESS, "/" },
-    { NULL, "/absolute//../path/", VINF_SUCCESS, "/path" },
-    { NULL, "/absolute/../../path", VINF_SUCCESS, "/path" },
-    { NULL, "relative/../dir/./././file.txt", VINF_SUCCESS, "%p/dir/file.txt" },
-    { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p/dir\\.\\.\\.\\file.txt" },  /* linux-specific */
-    { NULL, "/data/", VINF_SUCCESS, "/data" },
-    { "relative_base/dir/", "/from_root", VINF_SUCCESS, "/from_root" },
-    { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p/relative_base/dir/relative_also" },
-#endif
-#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
-    { NULL, "C:\\", VINF_SUCCESS, "C:\\" },
-    { "C:\\", "..", VINF_SUCCESS, "C:\\" },
-    { "C:\\temp", "..", VINF_SUCCESS, "C:\\" },
-    { "C:\\VirtualBox/Machines", "..\\VirtualBox.xml", VINF_SUCCESS, "C:\\VirtualBox\\VirtualBox.xml" },
-    { "C:\\MustDie", "\\from_root/dir/..", VINF_SUCCESS, "C:\\from_root" },
-    { "C:\\temp", "D:\\data", VINF_SUCCESS, "D:\\data" },
-    { NULL, "\\\\server\\..\\share", VINF_SUCCESS, "\\\\server\\..\\share" /* kind of strange */ },
-    { NULL, "\\\\server/", VINF_SUCCESS, "\\\\server\\" },
-    { NULL, "\\\\", VINF_SUCCESS, "\\\\" },
-    { NULL, "\\\\\\something", VINF_SUCCESS, "\\\\\\something" /* kind of strange */ },
-    { "\\\\server\\share_as_base", "/from_root", VINF_SUCCESS, "\\\\server\\from_root" },
-    { "\\\\just_server", "/from_root", VINF_SUCCESS, "\\\\just_server\\from_root" },
-    { "\\\\server\\share_as_base", "relative\\data", VINF_SUCCESS, "\\\\server\\share_as_base\\relative\\data" },
-    { "base", "\\\\?\\UNC\\relative/edwef/..", VINF_SUCCESS, "\\\\?\\UNC\\relative" },
-    { "\\\\?\\UNC\\base", "/from_root", VERR_INVALID_NAME, NULL },
-#else
-    { "/temp", "..", VINF_SUCCESS, "/" },
-    { "/VirtualBox/Machines", "../VirtualBox.xml", VINF_SUCCESS, "/VirtualBox/VirtualBox.xml" },
-    { "/MustDie", "/from_root/dir/..", VINF_SUCCESS, "/from_root" },
-    { "\\temp", "\\data", VINF_SUCCESS, "%p/\\temp/\\data" },
-#endif
-    };
-
-    for (unsigned i = 0; i < RT_ELEMENTS(s_aRTPathAbsExTests); ++ i)
-    {
-        rc = RTPathAbsEx(s_aRTPathAbsExTests[i].pcszInputBase,
-                         s_aRTPathAbsExTests[i].pcszInputPath,
-                         szPath, sizeof(szPath));
-        if (rc != s_aRTPathAbsExTests[i].rc)
-        {
-            RTTestIFailed("unexpected result code!\n"
-                          "   input base: '%s'\n"
-                          "   input path: '%s'\n"
-                          "       output: '%s'\n"
-                          "           rc: %Rrc\n"
-                          "  expected rc: %Rrc",
-                          s_aRTPathAbsExTests[i].pcszInputBase,
-                          s_aRTPathAbsExTests[i].pcszInputPath,
-                          szPath, rc,
-                          s_aRTPathAbsExTests[i].rc);
-            continue;
-        }
-
-        char szTmp[RTPATH_MAX];
-        char *pszExpected = NULL;
-        if (s_aRTPathAbsExTests[i].pcszOutput != NULL)
-        {
-            if (s_aRTPathAbsExTests[i].pcszOutput[0] == '%')
-            {
-                RTTESTI_CHECK_RC(rc = RTPathGetCurrent(szTmp, sizeof(szTmp)), VINF_SUCCESS);
-                if (RT_FAILURE(rc))
-                    break;
-
-                pszExpected = szTmp;
-
-                if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'p')
-                {
-                    cch = strlen(szTmp);
-                    if (cch + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
-                        strcpy(szTmp + cch, s_aRTPathAbsExTests[i].pcszOutput + 2);
-                }
-#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
-                else if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'd')
-                {
-                    if (2 + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
-                        strcpy(szTmp + 2, s_aRTPathAbsExTests[i].pcszOutput + 2);
-                }
-#endif
-            }
-            else
-            {
-                strcpy(szTmp, s_aRTPathAbsExTests[i].pcszOutput);
-                pszExpected = szTmp;
-            }
-
-            if (strcmp(szPath, pszExpected))
-            {
-                RTTestIFailed("Unexpected result\n"
-                              "   input base: '%s'\n"
-                              "   input path: '%s'\n"
-                              "       output: '%s'\n"
-                              "     expected: '%s'",
-                              s_aRTPathAbsExTests[i].pcszInputBase,
-                              s_aRTPathAbsExTests[i].pcszInputPath,
-                              szPath,
-                              s_aRTPathAbsExTests[i].pcszOutput);
-            }
-        }
-    }
-#endif
-
-    /*
-     * RTPathAbsExEx - will replace RTPathAbsEx shortly.
-     */
-    RTTestSub(hTest, "RTPathAbsExEx");
     static const struct
     {
@@ -477,8 +343,8 @@
 
         size_t cbAbsPath = sizeof(szPath);
-        rc = RTPathAbsExEx(s_aRTPathAbsExExTests[i].pcszInputBase,
-                           s_aRTPathAbsExExTests[i].pcszInputPath,
-                           s_aRTPathAbsExExTests[i].fFlags,
-                           szPath, &cbAbsPath);
+        rc = RTPathAbsEx(s_aRTPathAbsExExTests[i].pcszInputBase,
+                         s_aRTPathAbsExExTests[i].pcszInputPath,
+                         s_aRTPathAbsExExTests[i].fFlags,
+                         szPath, &cbAbsPath);
 
         if (RT_FAILURE(s_aRTPathAbsExExTests[i].rc))
