Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 45388)
+++ /trunk/include/iprt/err.h	(revision 45389)
@@ -655,4 +655,6 @@
 /** The request function is not implemented. */
 #define VERR_NOT_IMPLEMENTED                (-12)
+/** Invalid flags was given. */
+#define VERR_INVALID_FLAGS                  (-13)
 
 /** Not equal. */
@@ -979,4 +981,6 @@
 /** A path is not relative (start with root), expected an relative path. */
 #define VERR_PATH_IS_NOT_RELATIVE           (-144)
+/** Zero length path. */
+#define VERR_PATH_ZERO_LENGTH               (-145)
 /** @} */
 
Index: /trunk/include/iprt/path.h
===================================================================
--- /trunk/include/iprt/path.h	(revision 45388)
+++ /trunk/include/iprt/path.h	(revision 45389)
@@ -388,4 +388,276 @@
  */
 RTDECL(int) RTPathCopyComponents(char *pszDst, size_t cbDst, const char *pszSrc, size_t cComponents);
+
+/** @name Path properties returned by RTPathParse and RTPathSplit.
+ * @{ */
+
+/** Indicates that there is a filename.
+ * If not set, either a lone root spec was given (RTPATH_PROP_UNC,
+ * RTPATH_PROP_ROOT_SLASH, or RTPATH_PROP_VOLUME) or the final component had a
+ * trailing slash (RTPATH_PROP_DIR_SLASH). */
+#define RTPATH_PROP_FILENAME        UINT16_C(0x0001)
+/** Indicates that a directory was specified using a trailing slash.
+ * @note This is not set for lone root specifications (RTPATH_PROP_UNC,
+ *       RTPATH_PROP_ROOT_SLASH, or RTPATH_PROP_VOLUME).
+ * @note The slash is not counted into the last component.  */
+#define RTPATH_PROP_DIR_SLASH       UINT16_C(0x0002)
+
+/** The filename has a suffix (extension). */
+#define RTPATH_PROP_SUFFIX          UINT16_C(0x0004)
+/** Indicates that this is an UNC path (Windows and OS/2 only).
+ *
+ * UNC = Universal Naming Convention.  It is on the form '//Computer/',
+ * '//Namespace/', '//ComputerName/Resource' and '//Namespace/Resource'.
+ * RTPathParse, RTPathSplit and friends does not consider the 'Resource'  as
+ * part of the UNC root specifier.  Thus the root specs for the above examples
+ * would be '//ComputerName/' or '//Namespace/'.
+ *
+ * Please note that  '//something' is not a UNC path, there must be a slash
+ * following the computer or namespace.
+ */
+#define RTPATH_PROP_UNC             UINT16_C(0x0010)
+/** A root slash was specified (unix style root).
+ * (While the path must relative if not set, this being set doesn't make it
+ * absolute.)
+ *
+ * This will be set in the following examples: '/', '/bin', 'C:/', 'C:/Windows',
+ * '//./', '//./PhysicalDisk0', '//example.org/', and '//example.org/share'.
+ *
+ * It will not be set for the following examples: '.', 'bin/ls', 'C:', and
+ * 'C:Windows'.
+ */
+#define RTPATH_PROP_ROOT_SLASH      UINT16_C(0x0020)
+/** A volume is specified (Windows, DOS and OS/2).
+ * For examples: 'C:', 'C:/', and 'A:/AutoExec.bat'. */
+#define RTPATH_PROP_VOLUME          UINT16_C(0x0040)
+/** The path is absolute, i.e. has a root specifier (root-slash,
+ * volume or UNC) and contains no winding '..' bits, though it may contain
+ * unnecessary slashes (RTPATH_PROP_EXTRA_SLASHES) and '.' components
+ * (RTPATH_PROP_DOT_REFS).
+ *
+ * On systems without volumes and UNC (unix style) it will be set for '/',
+ * '/bin/ls', and '/bin//./ls', but not for 'bin/ls', /bin/../usr/bin/env',
+ * '/./bin/ls' or '/.'.
+ *
+ * On systems with volumes, it will be set for 'C:/', C:/Windows', and
+ * 'C:/./Windows//', but not for 'C:', 'C:Windows', or 'C:/Windows/../boot.ini'.
+ *
+ * On systems with UNC paths, it will be set for '//localhost/',
+ * '//localhost/C$', '//localhost/C$/Windows/System32', '//localhost/.', and
+ * '//localhost/C$//./AutoExec.bat', but not for
+ * '//localhost/C$/Windows/../AutoExec.bat'.
+ *
+ * @note For the RTPathAbs definition, this flag needs to be set while both
+ *       RTPATH_PROP_EXTRA_SLASHES and RTPATH_PROP_DOT_REFS must be cleared.
+ */
+#define RTPATH_PROP_ABSOLUTE        UINT16_C(0x0100)
+/** Relative path. Inverse of RTPATH_PROP_ABSOLUTE. */
+#define RTPATH_PROP_RELATIVE        UINT16_C(0x0200)
+/** The path contains unnecessary slashes. Meaning, that if  */
+#define RTPATH_PROP_EXTRA_SLASHES   UINT16_C(0x0400)
+/** The path contains references to the special '.' (dot) directory link. */
+#define RTPATH_PROP_DOT_REFS        UINT16_C(0x0800)
+/** The path contains references to the special '..' (dot) directory link.
+ * RTPATH_PROP_RELATIVE will always be set together with this.  */
+#define RTPATH_PROP_DOTDOT_REFS     UINT16_C(0x1000)
+
+
+/** Macro to determin whether to insert a slash after the first component when
+ * joining it with something else.
+ * (All other components in a split or parsed path requies slashes added.) */
+#define RTPATH_PROP_FIRST_NEEDS_NO_SLASH(a_fProps) \
+    ( (a_fProps) & (RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_VOLUME | RTPATH_PROP_UNC) )
+
+/** Macro to determin whether there is a root specification of any kind
+ * (unix, volumes, unc). */
+#define RTPATH_PROP_HAS_ROOT_SPEC(a_fProps) \
+    ( (a_fProps) & (RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_VOLUME | RTPATH_PROP_UNC) )
+
+/** @} */
+
+
+/**
+ * Parsed path.
+ *
+ * The first component is the root, volume or UNC specifier, if present.  Use
+ * RTPATH_PROP_HAS_ROOT_SPEC() on RTPATHPARSED::fProps to determine its
+ * precense.
+ *
+ * Other than the root component, no component will include directory separators
+ * (slashes).
+ */
+typedef struct RTPATHPARSED
+{
+    /** Number of path components.
+     * This will always be set on VERR_BUFFER_OVERFLOW returns from RTPathParsed
+     * so the caller can calculate the required buffer size. */
+    uint16_t    cComps;
+    /** Path property flags, RTPATH_PROP_XXX */
+    uint16_t    fProps;
+    /** On success this is the length of the described path, i.e. sum of all
+     * component lengths and necessary separators.
+     * Do NOT use this to index in the source path in case it contains
+     * unnecessary slashes that RTPathParsed has ignored here. */
+    uint16_t    cchPath;
+    /** Reserved for future use. */
+    uint16_t    u16Reserved;
+    /** The offset of the filename suffix, offset of the NUL char if none. */
+    uint16_t    offSuffix;
+    /** The lenght of the suffix. */
+    uint16_t    cchSuffix;
+    /** Array of component descriptors (variable size).
+     * @note Don't try figure the end of the input path by adding up off and cch
+     *       of the last component.  If RTPATH_PROP_DIR_SLASH is set, there may
+     *       be one or more trailing slashes that are unaccounted for! */
+    struct
+    {
+        /** The offset of the component. */
+        uint16_t    off;
+        /** The length of the component. */
+        uint16_t    cch;
+    } aComps[1];
+} RTPATHPARSED;
+/** Pointer to to a parsed path result. */
+typedef RTPATHPARSED *PRTPATHPARSED;
+/** Pointer to to a const parsed path result. */
+typedef RTPATHPARSED *PCRTPATHPARSED;
+
+
+/**
+ * Parses the path.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_INVALID_PARAMETER if cbOutput is less than the RTPATHPARSED
+ *          strucuture. No output. (asserted)
+ * @retval  VERR_BUFFER_OVERFLOW there are more components in the path than
+ *          there is space in aComps. The required amount of space can be
+ *          determined from the pParsed->cComps:
+ *          @code
+ *              RT_OFFSETOF(RTPATHPARSED, aComps[pParsed->cComps])
+ *          @endcode
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ *
+ * @param   pszPath             The path to parse.
+ * @param   pParsed             Where to store the details of the parsed path.
+ * @param   cbParsed            The size of the buffer. Must be at least the
+ *                              size of RTPATHPARSED.
+ * @param   fFlags              Combination of RTPATHPARSE_FLAGS_XXX that can be
+ *                              used to change how the start and end of the
+ *                              path is parsed. Most users will pass 0.
+ * @sa      RTPathSplit, RTPathSplitA.
+ */
+RTDECL(int) RTPathParse(const char *pszPath,  PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags);
+
+/** @name RTPATHPARSE_FLAGS_XXX - RTPathParse flags.
+ * @{ */
+/** Partial path - no start.
+ * This causes RTPathParse to skip the root specification parsing.  */
+#define RTPATHPARSE_FLAGS_NO_START          RT_BIT_32(0)
+/** Partial path - no end.
+ * This causes RTPathParse to skip the filename and dir-slash parsing.  */
+#define RTPATHPARSE_FLAGS_NO_END            RT_BIT_32(1)
+/** Partial path - no start and no end. */
+#define RTPATHPARSE_FLAGS_MIDDLE            (RTPATHPARSE_FLAGS_NO_START | RTPATHPARSE_FLAGS_NO_END)
+
+/** Host OS path style. */
+#define RTPATHPARSE_FLAGS_STYLE_HOST        UINT32_C(0x00000000)
+/** DOS, OS/2 and Windows path style. */
+#define RTPATHPARSE_FLAGS_STYLE_DOS         UINT32_C(0x00000010)
+/** Unix path style. */
+#define RTPATHPARSE_FLAGS_STYLE_UNIX        UINT32_C(0x00000020)
+/** Reserved path style. */
+#define RTPATHPARSE_FLAGS_STYLE_RESERVED    UINT32_C(0x00000030)
+/** The path style mask. */
+#define RTPATHPARSE_FLAGS_STYLE_MASK        UINT32_C(0x00000030)
+
+/** Mask containing the valid flags. */
+#define RTPATHPARSE_FLAGS_VALID_MASK        UINT32_C(0x00000033)
+/** @}  */
+
+/**
+ * Output buffer for RTPathSplit and RTPathSplitA.
+ */
+typedef struct RTPATHSPLIT
+{
+    /** Number of path components.
+     * This will always be set on VERR_BUFFER_OVERFLOW returns from RTPathParsed
+     * so the caller can calculate the required buffer size. */
+    uint16_t    cComps;
+    /** Path property flags, RTPATH_PROP_XXX */
+    uint16_t    fProps;
+    /** On success this is the length of the described path, i.e. sum of all
+     * component lengths and necessary separators.
+     * Do NOT use this to index in the source path in case it contains
+     * unnecessary slashes that RTPathParsed has ignored here. */
+    uint16_t    cchPath;
+    /** Reserved (internal use).  */
+    uint16_t    u16Reserved;
+    /** The amount of memory used (on success) or required (on
+     *  VERR_BUFFER_OVERFLOW) of this structure and it's strings. */
+    uint32_t    cbNeeded;
+    /** Pointer to the filename suffix (the dot), if any. Points to the NUL
+     * character of the last component if none or if RTPATH_PROP_DIR_SLASH is
+     * present. */
+    const char *pszSuffix;
+    /** Array of component strings (variable size). */
+    char       *apszComps[1];
+} RTPATHSPLIT;
+/** Pointer to a split path buffer. */
+typedef RTPATHSPLIT *PRTPATHSPLIT;
+/** Pointer to a const split path buffer. */
+typedef RTPATHSPLIT const *PCRTPATHSPLIT;
+
+/**
+ * Splits the path into individual component strings, carved from user supplied
+ * the given buffer block.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_INVALID_PARAMETER if cbOutput is less than the RTPATHSPLIT
+ *          strucuture. No output. (asserted)
+ * @retval  VERR_BUFFER_OVERFLOW there are more components in the path than
+ *          there is space in aComps. The required amount of space can be
+ *          determined from the pParsed->cComps:
+ *          @code
+ *              RT_OFFSETOF(RTPATHPARSED, aComps[pParsed->cComps])
+ *          @endcode
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ * @retval  VERR_FILENAME_TOO_LONG if the filename is too long (close to 64 KB).
+ *
+ * @param   pszPath             The path to parse.
+ * @param   pSplit              Where to store the details of the parsed path.
+ * @param   cbSplit             The size of the buffer pointed to by @a pSplit
+ *                              (variable sized array at the end).  Must be at
+ *                              least the size of RTPATHSPLIT.
+ *
+ * @sa      RTPathSplitA, RTPathParse.
+ */
+RTDECL(int) RTPathSplit(const char *pszPath, PRTPATHSPLIT pSplit, size_t cbSplit);
+
+/**
+ * Splits the path into individual component strings, allocating the buffer on
+ * the default thread heap.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_INVALID_POINTER if pParsed or pszPath is an invalid pointer.
+ * @retval  VERR_PATH_ZERO_LENGTH if the path is empty.
+ *
+ * @param   pszPath             The path to parse.
+ * @param   ppSplit             Where to return the pointer to the output on
+ *                              success.  This must be freed by calling
+ *                              RTPathSplitFree().
+ * @sa      RTPathSplitFree, RTPathSplit, RTPathParse.
+ */
+RTDECL(int) RTPathSplitA(const char *pszPath, PRTPATHSPLIT *ppSplit);
+
+/**
+ * Frees buffer returned by RTPathSplitA.
+ *
+ * @param   pSplit              What RTPathSplitA returned.
+ * @sa      RTPathSplitA
+ */
+RTDECL(void) RTPathSplitFree(PRTPATHSPLIT pSplit);
+
 
 /**
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 45388)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 45389)
@@ -362,4 +362,5 @@
 	common/path/RTPathJoinA.cpp \
 	common/path/RTPathJoinEx.cpp \
+	common/path/RTPathParse.cpp \
 	common/path/RTPathParseSimple.cpp \
 	common/path/RTPathRealDup.cpp \
@@ -1709,4 +1710,5 @@
 	common/path/RTPathHasExt.cpp \
 	common/path/RTPathHasPath.cpp \
+	common/path/RTPathParse.cpp \
 	common/path/RTPathParseSimple.cpp \
 	common/path/RTPathRealDup.cpp \
Index: /trunk/src/VBox/Runtime/common/path/RTPathParse.cpp.h
===================================================================
--- /trunk/src/VBox/Runtime/common/path/RTPathParse.cpp.h	(revision 45389)
+++ /trunk/src/VBox/Runtime/common/path/RTPathParse.cpp.h	(revision 45389)
@@ -0,0 +1,243 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTPathParse - Code Template.
+ *
+ * This file included multiple times with different path style macros.
+ */
+
+/*
+ * Copyright (C) 2006-2013 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.
+ */
+
+
+
+/**
+ * @copydoc RTPathParse
+ */
+static int RTPATH_STYLE_FN(rtPathParse)(const char *pszPath, PRTPATHPARSED pParsed, size_t cbParsed, uint32_t fFlags)
+{
+    /*
+     * Parse the root specification if present and initialize the parser state
+     * (keep it on the stack for speed).
+     */
+    uint32_t const  cMaxComps =  cbParsed < RT_UOFFSETOF(RTPATHPARSED, aComps[0xfff0])
+                              ? (cbParsed - RT_UOFFSETOF(RTPATHPARSED, aComps)) / sizeof(pParsed->aComps[0])
+                              : 0xfff0;
+    uint32_t        idxComp   = 0;
+    uint32_t        cchPath;
+    uint32_t        offCur;
+    uint16_t        fProps;
+
+    if (RTPATH_IS_SLASH(pszPath[0]))
+    {
+        if (fFlags & RTPATHPARSE_FLAGS_NO_START)
+        {
+            offCur = 1;
+            while (RTPATH_IS_SLASH(pszPath[offCur]))
+                offCur++;
+            if (!pszPath[offCur])
+                return VERR_PATH_ZERO_LENGTH;
+            fProps = RTPATH_PROP_RELATIVE | RTPATH_PROP_EXTRA_SLASHES;
+            cchPath = 0;
+        }
+#ifdef RTPATH_STYLE_DOS
+        else if (   RTPATH_IS_SLASH(pszPath[1])
+                 && !RTPATH_IS_SLASH(pszPath[2])
+                 && pszPath[2])
+        {
+            /* UNC - skip to the end of the potential namespace or computer name. */
+            offCur = 2;
+            while (!RTPATH_IS_SLASH(pszPath[offCur]) && pszPath[offCur])
+                offCur++;
+
+            /* If there is another slash, we considered it a valid UNC path, if
+               not it's just a root path with an extra slash thrown in. */
+            if (RTPATH_IS_SLASH(pszPath[offCur]))
+            {
+                fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_UNC | RTPATH_PROP_ABSOLUTE;
+                offCur++;
+            }
+            else
+            {
+                fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE;
+                offCur = 1;
+            }
+        }
+#endif
+        else
+        {
+#ifdef RTPATH_STYLE_DOS
+            fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE;
+#else
+            fProps = RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE;
+#endif
+            offCur = 1;
+        }
+    }
+#ifdef RTPATH_STYLE_DOS
+    else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
+    {
+        if (!RTPATH_IS_SLASH(pszPath[2]))
+        {
+            fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE;
+            offCur = 2;
+        }
+        else
+        {
+            fProps = RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE;
+            offCur = 3;
+        }
+    }
+#endif
+    else
+    {
+        fProps  = RTPATH_PROP_RELATIVE;
+        offCur  = 0;
+        cchPath = 0;
+    }
+
+    /*  Add it to the component array . */
+    if (offCur && !(fFlags & RTPATHPARSE_FLAGS_NO_START))
+    {
+        cchPath = offCur;
+        if (idxComp < cMaxComps)
+        {
+            pParsed->aComps[idxComp].off = 0;
+            pParsed->aComps[idxComp].cch = offCur;
+        }
+        idxComp++;
+
+        /* Skip unnecessary slashes following the root-spec. */
+        if (RTPATH_IS_SLASH(pszPath[offCur]))
+        {
+            fProps |= RTPATH_PROP_EXTRA_SLASHES;
+            do
+                offCur++;
+            while (RTPATH_IS_SLASH(pszPath[offCur]));
+        }
+    }
+
+    /*
+     * Parse the rest.
+     */
+    if (pszPath[offCur])
+    {
+        for (;;)
+        {
+            Assert(!RTPATH_IS_SLASH(pszPath[offCur]));
+
+            /* Find the end of the component. */
+            uint32_t    offStart = offCur;
+            char        ch;
+            while ((ch = pszPath[offCur]) != '\0' && !RTPATH_IS_SLASH(ch))
+                offCur++;
+            if (offCur >= _64K)
+                return VERR_FILENAME_TOO_LONG;
+
+            /* Add it. */
+            uint32_t cchComp = offCur - offStart;
+            if (idxComp < cMaxComps)
+            {
+                pParsed->aComps[idxComp].off = offStart;
+                pParsed->aComps[idxComp].cch = cchComp;
+            }
+            idxComp++;
+            cchPath += cchComp;
+
+            /* Look for '.' and '..' references. */
+            if (cchComp == 1 && pszPath[offCur - 1] == '.')
+                fProps |= RTPATH_PROP_DOT_REFS;
+            else if (cchComp == 2 && pszPath[offCur - 1] == '.' && pszPath[offCur - 2] == '.')
+            {
+                fProps &= ~RTPATH_PROP_ABSOLUTE;
+                fProps |= RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_RELATIVE;
+            }
+
+            /* Skip unnecessary slashes. Leave ch unchanged! */
+            char ch2 = ch;
+            if (ch2)
+            {
+                ch2 = pszPath[++offCur];
+                if (RTPATH_IS_SLASH(ch2))
+                {
+                    fProps |= RTPATH_PROP_EXTRA_SLASHES;
+                    do
+                        ch2 = pszPath[++offCur];
+                    while (RTPATH_IS_SLASH(ch2));
+                }
+            }
+
+            /* The end? */
+            if (ch2 == '\0')
+            {
+                pParsed->offSuffix = offCur;
+                pParsed->cchSuffix = 0;
+                if (ch)
+                {
+                    if (!(fFlags & RTPATHPARSE_FLAGS_NO_END))
+                        fProps |= RTPATH_PROP_DIR_SLASH; /* (not counted) */
+                    else
+                        fProps |= RTPATH_PROP_EXTRA_SLASHES;
+                }
+                else if (!(fFlags & RTPATHPARSE_FLAGS_NO_END))
+                {
+                    fProps |= RTPATH_PROP_FILENAME;
+
+                    /* look for an ? */
+                    uint16_t cDots  = 0;
+                    uint32_t offSuffix = offStart + cchComp;
+                    while (offSuffix-- > offStart)
+                        if (pszPath[offSuffix] == '.')
+                        {
+                            uint32_t cchSuffix = offStart + cchComp - offSuffix;
+                            if (cchSuffix > 1 && offStart != offSuffix)
+                            {
+                                pParsed->cchSuffix = cchSuffix;
+                                pParsed->offSuffix = offSuffix;
+                                fProps |= RTPATH_PROP_SUFFIX;
+                            }
+                            break;
+                        }
+                }
+                break;
+            }
+
+            /* No, not the end. Account for an separator before we restart the loop. */
+            cchPath += sizeof(RTPATH_SLASH_STR) - 1;
+        }
+    }
+    else
+    {
+        pParsed->offSuffix = offCur;
+        pParsed->cchSuffix = 0;
+    }
+    if (offCur >= _64K)
+        return VERR_FILENAME_TOO_LONG;
+
+    /*
+     * Store the remainder of the state and we're done.
+     */
+    pParsed->fProps  = fProps;
+    pParsed->cchPath = cchPath;
+    pParsed->cComps  = idxComp;
+
+    return idxComp <= cMaxComps ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW;
+}
+
Index: /trunk/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp	(revision 45388)
+++ /trunk/src/VBox/Runtime/common/path/rtPathRootSpecLen.cpp	(revision 45389)
@@ -55,5 +55,5 @@
     if (RTPATH_IS_SLASH(pszPath[0]))
     {
-#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
         if (   RTPATH_IS_SLASH(pszPath[1])
             && !RTPATH_IS_SLASH(pszPath[2])
@@ -79,5 +79,5 @@
             off++;
     }
-#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
     else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
     {
Index: /trunk/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h
===================================================================
--- /trunk/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h	(revision 45389)
+++ /trunk/src/VBox/Runtime/common/path/rtpath-expand-template.cpp.h	(revision 45389)
@@ -0,0 +1,76 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTPath - Internal header that includes RTPATH_TEMPLATE_CPP_H multiple
+ *                 times to expand the code for different path styles.
+ */
+
+/*
+ * Copyright (C) 2006-2013 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.
+ */
+
+
+/*
+ * The following should move to a helper header!
+ */
+#undef  RTPATH_DELIMITER
+
+/* DOS style */
+#undef  RTPATH_STYLE_UNIX
+#undef  RTPATH_STYLE_DOS
+#undef  RTPATH_SLASH_STR
+#undef  RTPATH_IS_SLASH
+#undef  RTPATH_IS_VOLSEP
+#undef  RTPATH_STYLE_FN
+
+#define RTPATH_STYLE_DOS
+#define RTPATH_SLASH_STR        "\\"
+#define RTPATH_IS_SLASH(a_ch)   ( (a_ch) == '\\' || (a_ch) == '/' )
+#define RTPATH_IS_VOLSEP(a_ch)  ( (a_ch) == ':' )
+#define RTPATH_STYLE_FN(a_Name) a_Name ## StyleDos
+#include RTPATH_TEMPLATE_CPP_H
+
+/* Unix style. */
+#undef  RTPATH_STYLE_UNIX
+#undef  RTPATH_STYLE_DOS
+#undef  RTPATH_SLASH_STR
+#undef  RTPATH_IS_SLASH
+#undef  RTPATH_IS_VOLSEP
+#undef  RTPATH_STYLE_FN
+
+#define RTPATH_STYLE_UNIX
+#define RTPATH_SLASH_STR        "/"
+#define RTPATH_IS_SLASH(a_ch)   ( (a_ch) == '/' )
+#define RTPATH_IS_VOLSEP(a_ch)  ( false )
+#define RTPATH_STYLE_FN(a_Name) a_Name ## StyleUnix
+#include RTPATH_TEMPLATE_CPP_H
+
+/* Restore original style. */
+#undef RTPATH_STYLE_FN
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# undef  RTPATH_STYLE_UNIX
+# undef  RTPATH_STYLE_DOS
+# undef  RTPATH_SLASH_STR
+# undef  RTPATH_IS_SLASH
+# undef  RTPATH_IS_VOLSEP
+# define RTPATH_SLASH_STR        "\\"
+# define RTPATH_IS_SLASH(a_ch)   ( (a_ch) == '\\' || (a_ch) == '/' )
+# define RTPATH_IS_VOLSEP(a_ch)  ( (a_ch) == ':' )
+#endif
+
Index: /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp	(revision 45388)
+++ /trunk/src/VBox/Runtime/testcase/tstRTPath.cpp	(revision 45389)
@@ -37,4 +37,84 @@
 #include <iprt/string.h>
 #include <iprt/test.h>
+
+
+static void testParser(RTTEST hTest)
+{
+    RTTestSub(hTest, "RTPathParse");
+
+    static struct
+    {
+        uint16_t    cComps;
+        uint16_t    cchPath;
+        uint16_t    offSuffix;
+        const char *pszPath;
+        uint16_t    fProps;
+        uint32_t    fFlags;
+    } const s_aTests[] =
+    {
+        { 2, 13,  9,  "C:/Config.sys",    RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX,       RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 2, 13, 10,  "C://Config.sys",   RTPATH_PROP_VOLUME | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX | RTPATH_PROP_EXTRA_SLASHES, RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 2, 12,  8,  "C:Config.sys",     RTPATH_PROP_VOLUME | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX,                                RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 1, 10,  6,  "Config.sys",       RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX,                                                     RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 1,  4,  4,  "//./",             RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE,                                                      RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 2,  5,  5,  "//./f",            RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                               RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 2,  5,  6,  "//.//f",           RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_EXTRA_SLASHES,   RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 3,  7,  7,  "//././f",          RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS,        RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 3,  8,  8,  "//.././f",         RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOT_REFS,        RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 3,  9,  9,  "//../../f",        RTPATH_PROP_UNC | RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME | RTPATH_PROP_DOTDOT_REFS,     RTPATHPARSE_FLAGS_STYLE_DOS },
+        { 1,  1,  1,  "/",                RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE,                                                                        RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 2,  4,  4,  "/bin",             RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 2,  4,  5,  "/bin/",            RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_DIR_SLASH,                                                RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 3,  7,  7,  "/bin/ls",          RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 3,  12, 7,  "/etc/rc.conf",     RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME | RTPATH_PROP_SUFFIX,                            RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 1,  1,  2,  "//",               RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES,                                            RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 1,  1,  3,  "///",              RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES,                                            RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 3,  6,  7,  "/.//bin",          RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_DOT_REFS | RTPATH_PROP_FILENAME, RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 1,  3,  3,  "bin",              RTPATH_PROP_RELATIVE | RTPATH_PROP_FILENAME,                                                                          RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 1,  3,  4,  "bin/",             RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH,                                                                         RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 1,  3,  7,  "bin////",          RTPATH_PROP_RELATIVE | RTPATH_PROP_DIR_SLASH | RTPATH_PROP_EXTRA_SLASHES,                                             RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 3, 10, 10,  "bin/../usr",       RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME,                                                RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4, 11, 11,  "/bin/../usr",      RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_RELATIVE | RTPATH_PROP_DOTDOT_REFS | RTPATH_PROP_FILENAME,                       RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/.../u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/.b./u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/..c/u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/d../u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/.e/.u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/.f/.u",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 4,  8,  8,  "/a/.g/u.",         RTPATH_PROP_ROOT_SLASH | RTPATH_PROP_ABSOLUTE | RTPATH_PROP_FILENAME,                                                 RTPATHPARSE_FLAGS_STYLE_UNIX },
+        { 3,  9, 10,  "/a/h/u.ext",       RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE,                                                                     RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
+        { 3,  9,  9,  "a/h/u.ext",        RTPATH_PROP_RELATIVE,                                                                                                 RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
+        { 3,  9, 10,  "a/h/u.ext/",       RTPATH_PROP_EXTRA_SLASHES | RTPATH_PROP_RELATIVE,                                                                     RTPATHPARSE_FLAGS_STYLE_UNIX | RTPATHPARSE_FLAGS_MIDDLE },
+    };
+
+    union
+    {
+        RTPATHPARSED    Parsed;
+        uint8_t         ab[4096];
+    } u;
+
+    for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++)
+    {
+        int rc = RTPathParse(s_aTests[i].pszPath, &u.Parsed, sizeof(u), s_aTests[i].fFlags);
+        if (   rc != VINF_SUCCESS
+            || s_aTests[i].cComps    != u.Parsed.cComps
+            || s_aTests[i].fProps    != u.Parsed.fProps
+            || s_aTests[i].offSuffix != u.Parsed.offSuffix
+            || s_aTests[i].cchPath   != u.Parsed.cchPath)
+        {
+            RTTestFailed(hTest, "i=%d rc=%Rrc %s", i, rc, s_aTests[i].pszPath);
+            RTTestFailureDetails(hTest,
+                                 "  cComps    %u, got %u\n"
+                                 "  fProps    %#x, got %#x, xor=>%#x\n"
+                                 "  offSuffix %u, got %u\n"
+                                 "  cchPath   %u, got %u\n"
+                                 ,
+                                 s_aTests[i].cComps,    u.Parsed.cComps,
+                                 s_aTests[i].fProps,    u.Parsed.fProps, s_aTests[i].fProps ^ u.Parsed.fProps,
+                                 s_aTests[i].offSuffix, u.Parsed.offSuffix,
+                                 s_aTests[i].cchPath,   u.Parsed.cchPath);
+        }
+    }
+}
 
 
@@ -596,4 +676,6 @@
     }
 
+    testParser(hTest);
+
     /*
      * Summary.
