Index: trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 69679)
+++ trunk/src/VBox/Runtime/common/vfs/vfsbase.cpp	(revision 69705)
@@ -1191,48 +1191,7 @@
 
 
-
-/**
- * Removes dots from the path.
- *
- * @returns The new @a pszDst value.
- * @param   pPath               The path parsing buffer.
- * @param   pszDst              The current szPath position.  This will be
- *                              updated and returned.
- * @param   fTheEnd             Indicates whether we're at the end of the path
- *                              or not.
- * @param   piRestartComp       The component to restart parsing at.
- */
-static char *rtVfsParsePathHandleDots(PRTVFSPARSEDPATH pPath, char *pszDst, bool fTheEnd, uint16_t *piRestartComp)
-{
-    if (pszDst[-1] != '.')
-        return pszDst;
-
-    if (pszDst[-2] == '/')
-    {
-        pPath->cComponents--;
-        pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
-    }
-    else if (pszDst[-2] == '.' && pszDst[-3] == '/')
-    {
-        pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1;
-        pszDst = &pPath->szPath[pPath->aoffComponents[pPath->cComponents]];
-        if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
-            *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
-    }
-    else
-        return pszDst;
-
-    /*
-     * Drop the trailing slash if we're at the end of the source path.
-     */
-    if (fTheEnd && pPath->cComponents == 0)
-        pszDst--;
-    return pszDst;
-}
-
-
 RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp)
 {
-    AssertReturn(*pszPath != '/', VERR_INTERNAL_ERROR_4);
+    AssertReturn(*pszPath != '/' && *pszPath != '\\', VERR_INTERNAL_ERROR_4);
 
     /* In case *piRestartComp was set higher than the number of components
@@ -1244,12 +1203,16 @@
      * Append a slash to the destination path if necessary.
      */
-    char *pszDst = &pPath->szPath[pPath->cch];
+    char * const pszDst         = pPath->szPath;
+    size_t       offDst         = pPath->cch;
     if (pPath->cComponents > 0)
     {
-        *pszDst++ = '/';
-        if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
+        pszDst[offDst++] = '/';
+        if (offDst >= RTVFSPARSEDPATH_MAX)
             return VERR_FILENAME_TOO_LONG;
     }
-    Assert(pszDst[-1] == '/');
+    if (pPath->fAbsolute)
+        Assert(pszDst[offDst - 1] == '/' && pszDst[0] == '/');
+    else
+        Assert(offDst == 0 || (pszDst[0] != '/' && pszDst[offDst - 1] == '/'));
 
     /*
@@ -1258,39 +1221,86 @@
     const char *pszSrc = pszPath;
     pPath->fDirSlash   = false;
-    while (pszSrc[0])
-    {
-        /* Skip unncessary slashes. */
-        while (pszSrc[0] == '/')
-            pszSrc++;
-
+    for (;;)
+    {
         /* Copy until we encounter the next slash. */
-        pPath->aoffComponents[pPath->cComponents++] = pszDst - &pPath->szPath[0];
-        while (pszSrc[0])
-        {
-            if (pszSrc[0] == '/')
+        pPath->aoffComponents[pPath->cComponents++] = (uint16_t)offDst;
+        for (;;)
+        {
+            char ch = *pszSrc++;
+            if (   ch != '/'
+                && ch != '\\'
+                && ch != '\0')
             {
-                pszSrc++;
-                if (pszSrc[0])
-                    *pszDst++ = '/';
+                pszDst[offDst++] = ch;
+                if (offDst < RTVFSPARSEDPATH_MAX)
+                { /* likely */ }
                 else
-                    pPath->fDirSlash = true;
-                pszDst = rtVfsParsePathHandleDots(pPath, pszDst, pszSrc[0] == '\0', piRestartComp);
+                    return VERR_FILENAME_TOO_LONG;
+            }
+            else
+            {
+                /* Deal with dot components before we processes the slash/end. */
+                if (pszDst[offDst - 1] == '.')
+                {
+                    if (   offDst == 1
+                        || pszDst[offDst - 2] == '/')
+                    {
+                        pPath->cComponents--;
+                        offDst = pPath->aoffComponents[pPath->cComponents];
+                    }
+                    else if (   offDst > 3
+                             && pszDst[offDst - 2] == '.'
+                             && pszDst[offDst - 3] == '/')
+                    {
+                        if (   pPath->fAbsolute
+                            || offDst < 5
+                            || pszDst[offDst - 4] != '.'
+                            || pszDst[offDst - 5] != '.'
+                            || (offDst >= 6 && pszDst[offDst - 6] != '/') )
+                        {
+                            pPath->cComponents -= pPath->cComponents > 1 ? 2 : 1;
+                            offDst = pPath->aoffComponents[pPath->cComponents];
+                            if (piRestartComp && *piRestartComp + 1 >= pPath->cComponents)
+                                *piRestartComp = pPath->cComponents > 0 ? pPath->cComponents - 1 : 0;
+                        }
+                    }
+                }
+
+                if (ch != '\0')
+                {
+                    /* Skip unnecessary slashes and check for end of path. */
+                    while ((ch = *pszSrc) == '/' || ch == '\\')
+                        pszSrc++;
+
+                    if (ch == '\0')
+                        pPath->fDirSlash = true;
+                }
+
+                if (ch == '\0')
+                {
+                    /* Drop trailing slash unless it's the root slash. */
+                    if (   offDst > 0
+                        && pszDst[offDst - 1] == '/'
+                        && (   !pPath->fAbsolute
+                            || offDst > 1))
+                        offDst--;
+
+                    /* Terminate the string and enter its length. */
+                    pszDst[offDst]     = '\0';
+                    pszDst[offDst + 1] = '\0'; /* for aoffComponents[pPath->cComponents] */
+                    pPath->cch = (uint16_t)offDst;
+                    pPath->aoffComponents[pPath->cComponents] = (uint16_t)(offDst + 1);
+                    return VINF_SUCCESS;
+                }
+
+                /* Append component separator before continuing with the next component. */
+                if (offDst > 0 && pszDst[offDst - 1] != '/')
+                    pszDst[offDst++] = '/';
+                if (offDst >= RTVFSPARSEDPATH_MAX)
+                    return VERR_FILENAME_TOO_LONG;
                 break;
             }
-
-            *pszDst++ = *pszSrc++;
-            if (pszDst - &pPath->szPath[0] >= RTVFSPARSEDPATH_MAX)
-                return VERR_FILENAME_TOO_LONG;
-        }
-    }
-    pszDst = rtVfsParsePathHandleDots(pPath, pszDst, true /*fTheEnd*/, piRestartComp);
-
-    /* Terminate the string and enter its length. */
-    pszDst[0] = '\0';
-    pszDst[1] = '\0';                   /* for aoffComponents */
-    pPath->cch = (uint16_t)(pszDst - &pPath->szPath[0]);
-    pPath->aoffComponents[pPath->cComponents] = pPath->cch + 1;
-
-    return VINF_SUCCESS;
+        }
+    }
 }
 
@@ -1301,10 +1311,27 @@
     if (*pszPath != '/')
     {
-        /*
-         * Relative, recurse and parse pszCwd first.
-         */
-        int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/);
-        if (RT_FAILURE(rc))
-            return rc;
+        if (pszCwd)
+        {
+            /*
+             * Relative with a CWD.
+             */
+            int rc = RTVfsParsePath(pPath, pszCwd, NULL /*crash if pszCwd is not absolute*/);
+            if (RT_FAILURE(rc))
+                return rc;
+        }
+        else
+        {
+            /*
+             * Relative.
+             */
+            pPath->cch               = 0;
+            pPath->cComponents       = 0;
+            pPath->fDirSlash         = false;
+            pPath->fAbsolute         = false;
+            pPath->aoffComponents[0] = 0;
+            pPath->aoffComponents[1] = 1;
+            pPath->szPath[0]         = '\0';
+            pPath->szPath[1]         = '\0';
+        }
     }
     else
@@ -1317,4 +1344,5 @@
         pPath->cComponents       = 0;
         pPath->fDirSlash         = false;
+        pPath->fAbsolute         = true;
         pPath->aoffComponents[0] = 1;
         pPath->aoffComponents[1] = 2;
@@ -2276,5 +2304,5 @@
      */
     PRTVFSPARSEDPATH pPath;
-    int rc = RTVfsParsePathA(pszPath, "/", &pPath);
+    int rc = RTVfsParsePathA(pszPath, NULL, &pPath);
     if (RT_SUCCESS(rc))
     {
@@ -2342,5 +2370,5 @@
      */
     PRTVFSPARSEDPATH pPath;
-    rc = RTVfsParsePathA(pszPath, "/", &pPath);
+    rc = RTVfsParsePathA(pszPath, NULL, &pPath);
     if (RT_SUCCESS(rc))
     {
@@ -2411,9 +2439,8 @@
 
     /*
-     * Parse the path, assume current directory is root since we've got no
-     * caller context here.  Then traverse to the parent directory.
+     * Parse the relative path.  Then traverse to the parent directory.
      */
     PRTVFSPARSEDPATH pPath;
-    int rc = RTVfsParsePathA(pszPath, "/", &pPath);
+    int rc = RTVfsParsePathA(pszPath, NULL, &pPath);
     if (RT_SUCCESS(rc))
     {
Index: trunk/src/VBox/Runtime/common/vfs/vfschain.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/vfs/vfschain.cpp	(revision 69679)
+++ trunk/src/VBox/Runtime/common/vfs/vfschain.cpp	(revision 69705)
@@ -145,5 +145,5 @@
         {
             /*
-             * First element: Ttransform into 'stdfile' or 'stddir' if registered.
+             * First element: Transform into 'stdfile' or 'stddir' if registered.
              */
             const char            *pszNewProvider = pElement->enmType == RTVFSOBJTYPE_DIR ? "stddir" : "stdfile";
@@ -177,5 +177,7 @@
             return VERR_VFS_CHAIN_INVALID_ARGUMENT;
         }
-    }
+        return rc;
+    }
+
 
     /*
@@ -184,4 +186,5 @@
     if (pElement->cArgs > 1)
         return VERR_VFS_CHAIN_AT_MOST_ONE_ARG;
+    pElement->uProvider = 0;
     return VINF_SUCCESS;
 }
