Index: /trunk/include/iprt/dvm.h
===================================================================
--- /trunk/include/iprt/dvm.h	(revision 73155)
+++ /trunk/include/iprt/dvm.h	(revision 73156)
@@ -55,4 +55,13 @@
     /** Volume hosts a FAT32 filesystem. */
     RTDVMVOLTYPE_FAT32,
+
+    /** EFI system partition (c12a7328-f81f-11d2-ba4b-00a0c93ec93b). */
+    RTDVMVOLTYPE_EFI_SYSTEM,
+
+    /** Volume hosts a Mac OS X HFS or HFS+ filesystem. */
+    RTDVMVOLTYPE_DARWIN_HFS,
+    /** Volume hosts a Mac OS X APFS filesystem. */
+    RTDVMVOLTYPE_DARWIN_APFS,
+
     /** Volume hosts a Linux swap. */
     RTDVMVOLTYPE_LINUX_SWAP,
@@ -63,4 +72,5 @@
     /** Volume hosts a Linux SoftRaid. */
     RTDVMVOLTYPE_LINUX_SOFTRAID,
+
     /** Volume hosts a FreeBSD disklabel. */
     RTDVMVOLTYPE_FREEBSD,
@@ -69,8 +79,23 @@
     /** Volume hosts a OpenBSD disklabel. */
     RTDVMVOLTYPE_OPENBSD,
-    /** Volume hosts a Mac OS X HFS or HFS+ filesystem. */
-    RTDVMVOLTYPE_MAC_OSX_HFS,
     /** Volume hosts a Solaris volume. */
     RTDVMVOLTYPE_SOLARIS,
+
+    /** Volume hosts a Windows basic data partition . */
+    RTDVMVOLTYPE_WIN_BASIC,
+    /** Volume hosts a Microsoft reserved partition (MSR). */
+    RTDVMVOLTYPE_WIN_MSR,
+    /** Volume hosts a Windows logical disk manager (LDM) metadata partition. */
+    RTDVMVOLTYPE_WIN_LDM_META,
+    /** Volume hosts a Windows logical disk manager (LDM) data partition. */
+    RTDVMVOLTYPE_WIN_LDM_DATA,
+    /** Volume hosts a Windows recovery partition. */
+    RTDVMVOLTYPE_WIN_RECOVERY,
+    /** Volume hosts a storage spaces partition. */
+    RTDVMVOLTYPE_WIN_STORAGE_SPACES,
+
+    /** Volume hosts an IBM general parallel file system (GPFS). */
+    RTDVMVOLTYPE_IBM_GPFS,
+
     /** End of the valid values. */
     RTDVMVOLTYPE_END,
Index: /trunk/src/VBox/Runtime/common/dvm/dvm.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvm.cpp	(revision 73155)
+++ /trunk/src/VBox/Runtime/common/dvm/dvm.cpp	(revision 73156)
@@ -121,13 +121,28 @@
     "FAT16",
     "FAT32",
+
+    "EFI system partition",
+
+    "Mac OS X HFS or HFS+",
+    "Mac OS X APFS",
+
     "Linux swap",
     "Linux native",
     "Linux LVM",
     "Linux SoftRaid",
+
     "FreeBSD",
     "NetBSD",
     "OpenBSD",
-    "Mac OS X HFS or HFS+",
-    "Solaris"
+    "Solaris",
+
+    "Basic data partition",
+    "Microsoft reserved partition",
+    "Windows LDM metadata",
+    "Windows LDM data",
+    "Windows recovery partition",
+    "Windows storage spaces",
+
+    "IBM GPFS",
 };
 AssertCompile(RT_ELEMENTS(g_apszDvmVolTypes) == RTDVMVOLTYPE_END);
Index: /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp	(revision 73155)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp	(revision 73156)
@@ -194,33 +194,49 @@
 static const RTDVMGPTPARTTYPE2VOLTYPE g_aPartType2DvmVolTypes[] =
 {
-    {"0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", RTDVMVOLTYPE_LINUX_SWAP},
-    {"EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", RTDVMVOLTYPE_LINUX_NATIVE},
-    {"E6D6D379-F507-44C2-A23C-238F2A3DF928", RTDVMVOLTYPE_LINUX_LVM},
-    {"A19D880F-05FC-4D3B-A006-743F0F84911E", RTDVMVOLTYPE_LINUX_SOFTRAID},
-
-    {"83BD6B9D-7F41-11DC-BE0B-001560B84F0F", RTDVMVOLTYPE_FREEBSD}, /* Boot */
-    {"516E7CB4-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD}, /* Data */
-    {"516E7CB5-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD}, /* Swap */
-    {"516E7CB6-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD}, /* UFS */
-    {"516E7CB8-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD}, /* Vinum */
-    {"516E7CBA-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD}, /* ZFS */
-
-    {"49F48D32-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* Swap */
-    {"49F48D5A-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* FFS */
-    {"49F48D82-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* LFS */
-    {"49F48DAA-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* Raid */
-    {"2DB519C4-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* Concatenated */
-    {"2DB519EC-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD}, /* Encrypted */
-
-    {"48465300-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_MAC_OSX_HFS},
-
-    {"6A82CB45-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* Boot */
-    {"6A85CF4D-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* Root */
-    {"6A87C46F-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* Swap */
-    {"6A8B642B-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* Backup */
-    {"6A898CC3-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* /usr */
-    {"6A8EF2E9-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* /var */
-    {"6A90BA39-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* /home */
-    {"6A9283A5-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS}, /* Alternate sector */
+    { "C12A7328-F81F-11D2-BA4B-00A0C93EC93B", RTDVMVOLTYPE_EFI_SYSTEM },
+
+    { "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7", RTDVMVOLTYPE_WIN_BASIC },
+    { "E3C9E316-0B5C-4DB8-817D-F92DF00215AE", RTDVMVOLTYPE_WIN_MSR },
+    { "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3", RTDVMVOLTYPE_WIN_LDM_META },
+    { "AF9B60A0-1431-4F62-BC68-3311714A69AD", RTDVMVOLTYPE_WIN_LDM_DATA },
+    { "DE94BBA4-06D1-4D40-A16A-BFD50179D6AC", RTDVMVOLTYPE_WIN_RECOVERY },
+    { "E75CAF8F-F680-4CEE-AFA3-B001E56EFC2D", RTDVMVOLTYPE_WIN_STORAGE_SPACES },
+
+    { "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F", RTDVMVOLTYPE_LINUX_SWAP },
+    { "0FC63DAF-8483-4772-8E79-3D69D8477DE4", RTDVMVOLTYPE_LINUX_NATIVE },
+    { "44479540-F297-41B2-9AF7-D131D5F0458A", RTDVMVOLTYPE_LINUX_NATIVE }, /* x86 root */
+    { "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709", RTDVMVOLTYPE_LINUX_NATIVE }, /* AMD64 root */
+    { "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3", RTDVMVOLTYPE_LINUX_NATIVE }, /* ARM32 root */
+    { "B921B045-1DF0-41C3-AF44-4C6F280D3FAE", RTDVMVOLTYPE_LINUX_NATIVE }, /* ARM64 root */
+    { "E6D6D379-F507-44C2-A23C-238F2A3DF928", RTDVMVOLTYPE_LINUX_LVM },
+    { "A19D880F-05FC-4D3B-A006-743F0F84911E", RTDVMVOLTYPE_LINUX_SOFTRAID },
+
+    { "83BD6B9D-7F41-11DC-BE0B-001560B84F0F", RTDVMVOLTYPE_FREEBSD }, /* Boot */
+    { "516E7CB4-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Data */
+    { "516E7CB5-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Swap */
+    { "516E7CB6-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* UFS */
+    { "516E7CB8-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* Vinum */
+    { "516E7CBA-6ECF-11D6-8FF8-00022D09712B", RTDVMVOLTYPE_FREEBSD }, /* ZFS */
+
+    { "49F48D32-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Swap */
+    { "49F48D5A-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* FFS */
+    { "49F48D82-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* LFS */
+    { "49F48DAA-B10E-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Raid */
+    { "2DB519C4-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Concatenated */
+    { "2DB519EC-B10F-11DC-B99B-0019D1879648", RTDVMVOLTYPE_NETBSD }, /* Encrypted */
+
+    { "48465300-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_DARWIN_HFS },
+    { "7C3457EF-0000-11AA-AA11-00306543ECAC", RTDVMVOLTYPE_DARWIN_APFS },
+
+    { "6A82CB45-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Boot */
+    { "6A85CF4D-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Root */
+    { "6A87C46F-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Swap */
+    { "6A8B642B-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Backup */
+    { "6A898CC3-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /usr */
+    { "6A8EF2E9-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /var */
+    { "6A90BA39-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* /home */
+    { "6A9283A5-1DD2-11B2-99A6-080020736631", RTDVMVOLTYPE_SOLARIS }, /* Alternate sector */
+
+    { "37AFFC90-EF7D-4E96-91C3-2D7AE055B174", RTDVMVOLTYPE_IBM_GPFS },
 };
 
Index: /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp	(revision 73155)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp	(revision 73156)
@@ -176,5 +176,5 @@
     { 0xa9, RTDVMVOLTYPE_NETBSD },
     { 0xa6, RTDVMVOLTYPE_OPENBSD },
-    { 0xaf, RTDVMVOLTYPE_MAC_OSX_HFS },
+    { 0xaf, RTDVMVOLTYPE_DARWIN_HFS },
     { 0xbf, RTDVMVOLTYPE_SOLARIS },
     { 0xfd, RTDVMVOLTYPE_LINUX_SOFTRAID }
Index: /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp	(revision 73155)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmvfs.cpp	(revision 73156)
@@ -48,39 +48,6 @@
 *   Structures and Typedefs                                                                                                      *
 *********************************************************************************************************************************/
-/**
- * A volume manager VFS for use in chains (thing pseudo/devfs).
- */
-typedef struct RTDVMVFSVOL
-{
-    /** The volume manager. */
-    RTDVM           hVolMgr;
-    /** Whether to close it on success. */
-    bool            fCloseDvm;
-    /** Whether the access is read-only. */
-    bool            fReadOnly;
-    /** Number of volumes. */
-    uint32_t        cVolumes;
-    /** Self reference. */
-    RTVFS           hVfsSelf;
-} RTDVMVFSVOL;
-/** Poitner to a volume manager VFS. */
-typedef RTDVMVFSVOL *PRTDVMVFSVOL;
-
-/**
- * The volume manager VFS (root) dir data.
- */
-typedef struct RTDVMVFSDIR
-{
-    /** Pointer to the VFS volume. */
-    PRTDVMVFSVOL    pVfsVol;
-    /** The current directory offset. */
-    uint32_t        offDir;
-    /** Set if we need to try return hCurVolume again because of buffer overflow. */
-    bool            fReturnCurrent;
-    /** The current DVM volume. */
-    RTDVMVOLUME     hCurVolume;
-} RTDVMVFSDIR;
-/** Poitner to a volume manager VFS (root) dir. */
-typedef RTDVMVFSDIR *PRTDVMVFSDIR;
+/** Pointer to a volume manager VFS. */
+typedef struct RTDVMVFSVOL *PRTDVMVFSVOL;
 
 /**
@@ -103,4 +70,57 @@
 typedef RTVFSDVMFILE *PRTVFSDVMFILE;
 
+/**
+ * The internal data of a DVM volume symlink.
+ */
+typedef struct RTVFSDVMSYMLINK
+{
+    /** The DVM volume the symlink represent. */
+    RTDVMVOLUME     hVol;
+    /** The DVM volume manager @a hVol belongs to. */
+    RTDVM           hVolMgr;
+    /** The symlink name. */
+    char           *pszSymlink;
+    /** The symlink target (volXX). */
+    char            szTarget[16];
+} RTVFSDVMSYMLINK;
+/** Pointer to a the internal data of a DVM volume file. */
+typedef RTVFSDVMSYMLINK *PRTVFSDVMSYMLINK;
+
+/**
+ * The volume manager VFS (root) dir data.
+ */
+typedef struct RTDVMVFSDIR
+{
+    /** Pointer to the VFS volume. */
+    PRTDVMVFSVOL    pVfsVol;
+    /** The current directory offset. */
+    uint32_t        offDir;
+    /** Set if we need to try return hCurVolume again because of buffer overflow. */
+    bool            fReturnCurrent;
+    /** Pointer to name alias string (returned by RTDvmVolumeQueryName, free it). */
+    char           *pszNameAlias;
+    /** The current DVM volume. */
+    RTDVMVOLUME     hCurVolume;
+} RTDVMVFSDIR;
+/** Pointer to a volume manager VFS (root) dir. */
+typedef RTDVMVFSDIR *PRTDVMVFSDIR;
+
+/**
+ * A volume manager VFS for use in chains (thing pseudo/devfs).
+ */
+typedef struct RTDVMVFSVOL
+{
+    /** The volume manager. */
+    RTDVM           hVolMgr;
+    /** Whether to close it on success. */
+    bool            fCloseDvm;
+    /** Whether the access is read-only. */
+    bool            fReadOnly;
+    /** Number of volumes. */
+    uint32_t        cVolumes;
+    /** Self reference. */
+    RTVFS           hVfsSelf;
+} RTDVMVFSVOL;
+
 
 /*********************************************************************************************************************************
@@ -123,23 +143,9 @@
 
 /**
- * Worker for rtDvmVfsFile_QueryInfo, rtDvmVfsDir_QueryEntryInfo, and
- * rtDvmVfsDir_ReadDir.
- */
-static int rtDvmVfsFile_QueryInfoWorker(RTDVMVOLUME hVolume, RTDVM hVolMgr, bool fReadOnly,
-                                        PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
-{
-
-    pObjInfo->cbObject    = RTDvmVolumeGetSize(hVolume);
-    pObjInfo->cbAllocated = pObjInfo->cbObject;
-    RTTimeSpecSetNano(&pObjInfo->AccessTime, 0);
-    RTTimeSpecSetNano(&pObjInfo->ModificationTime, 0);
-    RTTimeSpecSetNano(&pObjInfo->ChangeTime, 0);
-    RTTimeSpecSetNano(&pObjInfo->BirthTime, 0);
-    pObjInfo->Attr.fMode = RTFS_TYPE_FILE | RTFS_DOS_NT_NORMAL;
-    if (fReadOnly)
-        pObjInfo->Attr.fMode |= RTFS_DOS_READONLY | 0444;
-    else
-        pObjInfo->Attr.fMode |= 0666;
-
+ * Worker for rtDvmVfsFile_QueryInfoWorker and rtDvmVfsSym_QueryInfoWorker.
+ */
+static int rtDvmVfsFileSym_QueryAddAttrWorker(RTDVMVOLUME hVolume, RTDVM hVolMgr,
+                                              PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
     switch (enmAddAttr)
     {
@@ -187,4 +193,28 @@
     }
     return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for rtDvmVfsFile_QueryInfo, rtDvmVfsDir_QueryEntryInfo, and
+ * rtDvmVfsDir_ReadDir.
+ */
+static int rtDvmVfsFile_QueryInfoWorker(RTDVMVOLUME hVolume, RTDVM hVolMgr, bool fReadOnly,
+                                        PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
+
+    pObjInfo->cbObject    = RTDvmVolumeGetSize(hVolume);
+    pObjInfo->cbAllocated = pObjInfo->cbObject;
+    RTTimeSpecSetNano(&pObjInfo->AccessTime, 0);
+    RTTimeSpecSetNano(&pObjInfo->ModificationTime, 0);
+    RTTimeSpecSetNano(&pObjInfo->ChangeTime, 0);
+    RTTimeSpecSetNano(&pObjInfo->BirthTime, 0);
+    pObjInfo->Attr.fMode = RTFS_TYPE_FILE | RTFS_DOS_NT_NORMAL;
+    if (fReadOnly)
+        pObjInfo->Attr.fMode |= RTFS_DOS_READONLY | 0444;
+    else
+        pObjInfo->Attr.fMode |= 0666;
+
+    return rtDvmVfsFileSym_QueryAddAttrWorker(hVolume, hVolMgr, pObjInfo, enmAddAttr);
 }
 
@@ -533,4 +563,147 @@
 
 
+/*********************************************************************************************************************************
+*   DVM Symbolic Link Objects                                                                                                    *
+*********************************************************************************************************************************/
+/**
+ * @interface_method_impl{RTVFSOBJOPS,pfnClose}
+ */
+static DECLCALLBACK(int) rtDvmVfsSym_Close(void *pvThis)
+{
+    PRTVFSDVMSYMLINK pThis = (PRTVFSDVMSYMLINK)pvThis;
+    if (pThis->pszSymlink)
+    {
+        RTStrFree(pThis->pszSymlink);
+        pThis->pszSymlink = NULL;
+    }
+    if (pThis->hVol != NIL_RTDVMVOLUME)
+    {
+        RTDvmVolumeRelease(pThis->hVol);
+        pThis->hVol = NIL_RTDVMVOLUME;
+    }
+    if (pThis->hVolMgr != NIL_RTDVM)
+    {
+        RTDvmRelease(pThis->hVolMgr);
+        pThis->hVolMgr = NIL_RTDVM;
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for rtDvmVfsSym_QueryInfo and rtDvmVfsDir_Read.
+ *
+ * @returns IPRT status code.
+ * @param   hVolume             The volume handle.
+ * @param   hVolMgr             The volume manager handle. Optional.
+ * @param   pszTarget           The link target.
+ * @param   pObjInfo            The object info structure to populate.
+ * @param   enmAddAttr          The additional attributes to supply.
+ */
+static int rtDvmVfsSym_QueryInfoWorker(RTDVMVOLUME hVolume, RTDVM hVolMgr, const char *pszTarget,
+                                       PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
+    RT_ZERO(*pObjInfo);
+    pObjInfo->cbObject = pObjInfo->cbAllocated = pszTarget ? strlen(pszTarget) : 0;
+    pObjInfo->Attr.fMode = 0777 | RTFS_TYPE_SYMLINK | RTFS_DOS_NT_REPARSE_POINT;
+
+    return rtDvmVfsFileSym_QueryAddAttrWorker(hVolume, hVolMgr, pObjInfo, enmAddAttr);
+}
+
+
+/**
+ * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
+ */
+static DECLCALLBACK(int) rtDvmVfsSym_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
+{
+    PRTVFSDVMSYMLINK pThis = (PRTVFSDVMSYMLINK)pvThis;
+    return rtDvmVfsSym_QueryInfoWorker(pThis->hVol, pThis->hVolMgr, pThis->szTarget, pObjInfo, enmAddAttr);
+}
+
+
+/**
+ * @interface_method_impl{RTVFSSYMLINKOPS,pfnRead}
+ */
+static DECLCALLBACK(int) rtDvmVfsSym_Read(void *pvThis, char *pszTarget, size_t cbTarget)
+{
+    PRTVFSDVMSYMLINK pThis = (PRTVFSDVMSYMLINK)pvThis;
+    return RTStrCopy(pszTarget, cbTarget, pThis->szTarget);
+}
+
+
+/**
+ * DVM symbolic link operations.
+ */
+static const RTVFSSYMLINKOPS g_rtDvmVfsSymOps =
+{
+    { /* Obj */
+        RTVFSOBJOPS_VERSION,
+        RTVFSOBJTYPE_SYMLINK,
+        "DvmSymlink",
+        rtDvmVfsSym_Close,
+        rtDvmVfsSym_QueryInfo,
+        RTVFSOBJOPS_VERSION
+    },
+    RTVFSSYMLINKOPS_VERSION,
+    0,
+    { /* ObjSet */
+        RTVFSOBJSETOPS_VERSION,
+        RT_UOFFSETOF(RTVFSSYMLINKOPS, ObjSet) - RT_UOFFSETOF(RTVFSSYMLINKOPS, Obj),
+        NULL /*rtDvmVfsSym_SetMode*/,
+        NULL /*rtDvmVfsSym_SetTimes*/,
+        NULL /*rtDvmVfsSym_SetOwner*/,
+        RTVFSOBJSETOPS_VERSION
+    },
+    rtDvmVfsSym_Read,
+    RTVFSSYMLINKOPS_VERSION
+};
+
+
+/**
+ * Internal worker for rtDvmVfsDir_OpenFile.
+ *
+ * @returns IPRT status code.
+ * @param   hVol                The volume handle (not consumed).
+ * @param   hVolMgr             The volume manager handle (not consumed).
+ * @param   iVol                The volume number.
+ * @param   pszSymlink          The volume name. Consumed on success.
+ * @param   phVfsSymlinkOut     Where to return the handle to the file.
+ */
+static int rtDvmVfsCreateSymlinkForVolume(RTDVMVOLUME hVol, RTDVM hVolMgr, uint32_t iVol, char *pszSymlink,
+                                          PRTVFSSYMLINK phVfsSymlinkOut)
+{
+    uint32_t cRefs = RTDvmVolumeRetain(hVol);
+    AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE);
+
+    cRefs = RTDvmRetain(hVolMgr);
+    AssertReturnStmt(cRefs != UINT32_MAX, RTDvmVolumeRelease(hVol), VERR_INVALID_HANDLE);
+
+    /*
+     * Create the symlink.
+     */
+    RTVFSSYMLINK        hVfsSym;
+    PRTVFSDVMSYMLINK    pThis;
+    int rc = RTVfsNewSymlink(&g_rtDvmVfsSymOps, sizeof(*pThis), NIL_RTVFS, NIL_RTVFSLOCK, &hVfsSym, (void **)&pThis);
+    if (RT_SUCCESS(rc))
+    {
+        pThis->hVol       = hVol;
+        pThis->hVolMgr    = hVolMgr;
+        pThis->pszSymlink = pszSymlink;
+        RTStrPrintf(pThis->szTarget, sizeof(pThis->szTarget), "vol%u", iVol);
+
+        *phVfsSymlinkOut = hVfsSym;
+        return VINF_SUCCESS;
+    }
+    RTDvmRelease(hVolMgr);
+    RTDvmVolumeRelease(hVol);
+    return rc;
+}
+
+
+
+/*********************************************************************************************************************************
+*   DVM Directory Objects                                                                                                        *
+*********************************************************************************************************************************/
+
 /**
  * @interface_method_impl{RTVFSOBJOPS,pfnClose}
@@ -544,4 +717,10 @@
         RTDvmVolumeRelease(pThis->hCurVolume);
         pThis->hCurVolume = NIL_RTDVMVOLUME;
+    }
+
+    if (pThis->pszNameAlias)
+    {
+        RTStrFree(pThis->pszNameAlias);
+        pThis->pszNameAlias = NULL;
     }
 
@@ -637,6 +816,11 @@
 
 
-static int rtDvmVfsDir_FindEntry(PRTDVMVFSDIR pThis, const char *pszEntry, PRTDVMVOLUME phVolume)
-{
+static int rtDvmVfsDir_FindEntry(PRTDVMVFSDIR pThis, const char *pszEntry,
+                                 PRTDVMVOLUME phVolume, uint32_t *piVol, char **ppszSymlink)
+{
+    *phVolume    = NIL_RTDVMVOLUME;
+    *ppszSymlink = NULL;
+    *piVol       = UINT32_MAX;
+
     /*
      * Enumerate the volumes and try match the volume name.
@@ -659,4 +843,11 @@
             {
                 fMatch = RTStrCmp(pszEntry, pszVolName) == 0 && *pszVolName != '\0';
+                if (fMatch)
+                {
+                    *phVolume    = hVol;
+                    *ppszSymlink = pszVolName;
+                    *piVol       = iVol;
+                    return VINF_SUCCESS;
+                }
                 RTStrFree(pszVolName);
             }
@@ -680,4 +871,5 @@
             {
                 *phVolume = hVol;
+                *piVol    = iVol;
                 return VINF_SUCCESS;
             }
@@ -744,6 +936,8 @@
      * Open volume file.
      */
-    RTDVMVOLUME hVolume = NIL_RTDVMVOLUME;
-    int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume);
+    RTDVMVOLUME hVolume    = NIL_RTDVMVOLUME;
+    uint32_t    iVol       = 0;
+    char       *pszSymlink = NULL;
+    int rc = rtDvmVfsDir_FindEntry(pThis, pszEntry, &hVolume, &iVol, &pszSymlink);
     if (RT_SUCCESS(rc))
     {
@@ -754,18 +948,38 @@
             if (fFlags & (RTVFSOBJ_F_OPEN_FILE | RTVFSOBJ_F_OPEN_DEV_BLOCK))
             {
-                if (   !(fOpen & RTFILE_O_WRITE)
-                    || !pThis->pVfsVol->fReadOnly)
+                if (!pszSymlink)
                 {
-                    RTVFSFILE hVfsFile;
-                    rc = rtDvmVfsCreateFileForVolume(pThis->pVfsVol, hVolume, fOpen, &hVfsFile);
-                    if (RT_SUCCESS(rc))
+                    if (   !(fOpen & RTFILE_O_WRITE)
+                        || !pThis->pVfsVol->fReadOnly)
                     {
-                        *phVfsObj = RTVfsObjFromFile(hVfsFile);
-                        RTVfsFileRelease(hVfsFile);
-                        AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                        /* Create file object. */
+                        RTVFSFILE hVfsFile;
+                        rc = rtDvmVfsCreateFileForVolume(pThis->pVfsVol, hVolume, fOpen, &hVfsFile);
+                        if (RT_SUCCESS(rc))
+                        {
+                            *phVfsObj = RTVfsObjFromFile(hVfsFile);
+                            RTVfsFileRelease(hVfsFile);
+                            AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                        }
                     }
+                    else
+                        rc = VERR_WRITE_PROTECT;
                 }
                 else
-                    rc = VERR_WRITE_PROTECT;
+                    rc = VERR_IS_A_SYMLINK;
+            }
+            else if (fFlags & RTVFSOBJ_F_OPEN_SYMLINK)
+            {
+                /* Create symlink object */
+                RTVFSSYMLINK hVfsSym;
+                rc = rtDvmVfsCreateSymlinkForVolume(hVolume, pThis->pVfsVol ? pThis->pVfsVol->hVolMgr : NIL_RTDVM, iVol,
+                                                    pszSymlink, &hVfsSym);
+                if (RT_SUCCESS(rc))
+                {
+                    *phVfsObj = RTVfsObjFromSymlink(hVfsSym);
+                    RTVfsSymlinkRelease(hVfsSym);
+                    AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3);
+                    pszSymlink = NULL;
+                }
             }
             else
@@ -775,4 +989,6 @@
             rc = VERR_ALREADY_EXISTS;
         RTDvmVolumeRelease(hVolume);
+        if (pszSymlink)
+            RTStrFree(pszSymlink);
     }
     return rc;
@@ -861,4 +1077,9 @@
     pThis->fReturnCurrent = false;
     pThis->offDir         = 0;
+    if (pThis->pszNameAlias)
+    {
+        RTStrFree(pThis->pszNameAlias);
+        pThis->pszNameAlias = NULL;
+    }
 
     return VINF_SUCCESS;
@@ -877,8 +1098,47 @@
 
     /*
-     * Get the volume to return info about.
-     */
+     * Format the volume name since we'll be needing it all but the final call.
+     */
+    char         szVolNo[16];
+    size_t const cchVolNo = RTStrPrintf(szVolNo, sizeof(szVolNo), "vol%u", pThis->offDir);
+
     if (!pThis->fReturnCurrent)
     {
+        /*
+         * Do we have a pending name alias to return?
+         */
+        if (pThis->pszNameAlias)
+        {
+            size_t cchNameAlias = strlen(pThis->pszNameAlias);
+            size_t cbNeeded     = RT_UOFFSETOF_DYN(RTDIRENTRYEX, szName[cchNameAlias + 1]);
+            if (cbNeeded <= *pcbDirEntry)
+            {
+                *pcbDirEntry = cbNeeded;
+
+                /* Do the names. */
+                pDirEntry->cbName = (uint16_t)cchNameAlias;
+                memcpy(pDirEntry->szName, pThis->pszNameAlias, cchNameAlias + 1);
+                pDirEntry->cwcShortName = 0;
+                pDirEntry->wszShortName[0] = '\0';
+
+
+                /* Do the rest. */
+                rc = rtDvmVfsSym_QueryInfoWorker(pThis->hCurVolume, pVfsVol->hVolMgr, szVolNo, &pDirEntry->Info, enmAddAttr);
+                if (RT_SUCCESS(rc))
+                {
+                    RTStrFree(pThis->pszNameAlias);
+                    pThis->pszNameAlias = NULL;
+                    pThis->offDir      += 1;
+                }
+                return rc;
+            }
+
+            *pcbDirEntry = cbNeeded;
+            return VERR_BUFFER_OVERFLOW;
+        }
+
+        /*
+         * Get the next volume to return info about.
+         */
         if (pThis->offDir < pVfsVol->cVolumes)
         {
@@ -892,4 +1152,14 @@
             RTDvmVolumeRelease(pThis->hCurVolume);
             pThis->hCurVolume = hNextVolume;
+
+            /* Check if we need to return a name alias later. */
+            rc = RTDvmVolumeQueryName(pThis->hCurVolume, &pThis->pszNameAlias);
+            if (RT_FAILURE(rc))
+                pThis->pszNameAlias = NULL;
+            else if (*pThis->pszNameAlias == '\0')
+            {
+                RTStrFree(pThis->pszNameAlias);
+                pThis->pszNameAlias = NULL;
+            }
         }
         else
@@ -904,60 +1174,30 @@
      * Figure out the name length.
      */
-    char szVolNo[16];
-    RTStrPrintf(szVolNo, sizeof(szVolNo), "vol%u", pThis->offDir);
-
-    char *pszVolName;
-    rc = RTDvmVolumeQueryName(pThis->hCurVolume, &pszVolName);
-    if (   RT_SUCCESS(rc)
-        || rc == VERR_NOT_SUPPORTED)
-    {
-        if (rc == VERR_NOT_SUPPORTED)
-            pszVolName = szVolNo;
-        else if (*pszVolName == '\0')
+    size_t cbNeeded = RT_UOFFSETOF_DYN(RTDIRENTRYEX, szName[cchVolNo + 1]);
+    if (cbNeeded <= *pcbDirEntry)
+    {
+        *pcbDirEntry = cbNeeded;
+
+        /* Do the names. */
+        pDirEntry->cbName = (uint16_t)cchVolNo;
+        memcpy(pDirEntry->szName, szVolNo, cchVolNo + 1);
+        pDirEntry->cwcShortName = 0;
+        pDirEntry->wszShortName[0] = '\0';
+
+        /* Do the rest. */
+        rc = rtDvmVfsFile_QueryInfoWorker(pThis->hCurVolume, pVfsVol->hVolMgr, pVfsVol->fReadOnly, &pDirEntry->Info, enmAddAttr);
+        if (RT_SUCCESS(rc))
         {
-            RTStrFree(pszVolName);
-            pszVolName = szVolNo;
-        }
-
-        size_t cchVolName = strlen(pszVolName);
-        size_t cbNeeded   = RT_UOFFSETOF_DYN(RTDIRENTRYEX,  szName[cchVolName + 1]);
-        if (cbNeeded <= *pcbDirEntry)
-        {
-            *pcbDirEntry = cbNeeded;
-
-            /* Do the names. */
-            pDirEntry->cbName = (uint16_t)cchVolName;
-            memcpy(pDirEntry->szName, pszVolName, cchVolName + 1);
-            if (pszVolName != szVolNo)
-            {
-                RTStrFree(pszVolName);
-
-                PRTUTF16 pwszShortName = pDirEntry->wszShortName;
-                size_t   cwcShortName = 0;
-                rc = RTStrToUtf16Ex(szVolNo, RTSTR_MAX, &pwszShortName, RT_ELEMENTS(pDirEntry->wszShortName), &cwcShortName);
-                AssertRC(rc);
-                pDirEntry->cwcShortName = (uint16_t)cwcShortName;
-            }
-            else
-            {
-                pDirEntry->cwcShortName = 0;
-                pDirEntry->wszShortName[0] = '\0';
-            }
-
-            /* Do the rest. */
-            rc = rtDvmVfsFile_QueryInfoWorker(pThis->hCurVolume, pVfsVol->hVolMgr, pVfsVol->fReadOnly,
-                                              &pDirEntry->Info, enmAddAttr);
-            pThis->fReturnCurrent = !RT_SUCCESS(rc);
-            pThis->offDir        += RT_SUCCESS(rc);
+            pThis->fReturnCurrent = false;
+            if (!pThis->pszNameAlias)
+                pThis->offDir += 1;
             return rc;
         }
-
+    }
+    else
+    {
         *pcbDirEntry = cbNeeded;
         rc = VERR_BUFFER_OVERFLOW;
-
-        if (pszVolName != szVolNo)
-            RTStrFree(pszVolName);
-    }
-
+    }
     pThis->fReturnCurrent = true;
     return rc;
@@ -1047,4 +1287,5 @@
         pNewDir->pVfsVol        = pThis;
         pNewDir->fReturnCurrent = false;
+        pNewDir->pszNameAlias   = NULL;
         pNewDir->hCurVolume     = NIL_RTDVMVOLUME;
     }
