Index: /trunk/include/VBox/shflsvc.h
===================================================================
--- /trunk/include/VBox/shflsvc.h	(revision 76664)
+++ /trunk/include/VBox/shflsvc.h	(revision 76665)
@@ -1501,4 +1501,30 @@
 #define SHFL_LIST_RESTART       2
 
+/** SHFL_FN_LIST parameters. */
+typedef struct VBoxSFParmList
+{
+    /** value32, in: SHFLROOT of the mapping the handle belongs to. */
+    HGCMFunctionParameter id32Root;
+    /** value64, in: SHFLHANDLE of the directory. */
+    HGCMFunctionParameter u64Handle;
+    /** value32, in: List flags SHFL_LIST_XXX. */
+    HGCMFunctionParameter f32Flags;
+    /** value32, in/out: Input buffer size / Returned bytes count. */
+    HGCMFunctionParameter cb32Buffer;
+    /** pointer, in[optional]: SHFLSTRING filter string (full path). */
+    HGCMFunctionParameter pStrFilter;
+    /** pointer, out: Buffer to return listing information in (SHFLDIRINFO).
+     * When SHFL_LIST_RETURN_ONE is not specfied, multiple record may be
+     * returned, deriving the entry size using SHFLDIRINFO::name.u16Size.  */
+    HGCMFunctionParameter pBuffer;
+    /** value32, out: Set to 1 if the listing is done, 0 if more entries.
+     * @note Must be set to zero on call as it was declared in/out parameter and
+     *       may be used as such again. */
+    HGCMFunctionParameter f32Done;
+    /** value32, out:  Number of entries returned. */
+    HGCMFunctionParameter c32Entries;
+} VBoxSFParmList;
+
+
 /** Parameters structure. */
 typedef struct _VBoxSFList
Index: /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp
===================================================================
--- /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp	(revision 76664)
+++ /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp	(revision 76665)
@@ -233,23 +233,27 @@
             || pEntry == NULL /* paranoia */)
         {
-            pDataBuf->pEntry  = pEntry = (PSHFLDIRINFO)(pDataBuf + 1);
-            pDataBuf->cbValid = pDataBuf->cbBuf - sizeof(*pDataBuf);
-            int vrc = VbglR0SfDirInfo(&g_SfClient, &pFolder->hHostFolder, pFsFsd->hHostDir, pDataBuf->pFilter,
-                                      cMaxMatches == 1 ? SHFL_LIST_RETURN_ONE : 0, 0 /*index*/, &pDataBuf->cbValid,
-                                      pEntry, &pDataBuf->cEntriesLeft);
+            pDataBuf->pEntry = pEntry = pDataBuf->pBuf;
+            int vrc = vboxSfOs2HostReqListDir(pFolder, &pDataBuf->Req, pFsFsd->hHostDir, pDataBuf->pFilter,
+                                              /*cMaxMatches == 1 ? SHFL_LIST_RETURN_ONE :*/ 0, pDataBuf->pBuf, pDataBuf->cbBuf);
             if (RT_SUCCESS(vrc))
             {
+                pDataBuf->cEntriesLeft = pDataBuf->Req.Parms.c32Entries.u.value32;
+                pDataBuf->cbValid      = pDataBuf->Req.Parms.cb32Buffer.u.value32;
+                //Log(("%.*Rhxd\n", pDataBuf->cbValid, pEntry));
                 AssertReturn(pDataBuf->cbValid >= RT_UOFFSETOF(SHFLDIRINFO, name.String), ERROR_SYS_INTERNAL);
                 AssertReturn(pDataBuf->cbValid >= RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size, ERROR_SYS_INTERNAL);
-                Log4(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo returned %#x matches in %#x bytes\n", pDataBuf->cEntriesLeft, pDataBuf->cbValid));
+                Log4(("vboxSfOs2ReadDirEntries: vboxSfOs2HostReqListDir returned %#x matches in %#x bytes\n", pDataBuf->cEntriesLeft, pDataBuf->cbValid));
             }
             else
             {
                 if (vrc == VERR_NO_MORE_FILES)
-                    Log(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo failed %Rrc (%d,%d)\n", vrc, pDataBuf->cEntriesLeft, pDataBuf->cbValid));
+                    Log4(("vboxSfOs2ReadDirEntries: vboxSfOs2HostReqListDir returned VERR_NO_MORE_FILES (%d,%d)\n",
+                          pDataBuf->Req.Parms.c32Entries.u.value32, pDataBuf->Req.Parms.cb32Buffer.u.value32));
                 else
-                    Log4(("vboxSfOs2ReadDirEntries: VbglR0SfDirInfo returned VERR_NO_MORE_FILES (%d,%d)\n", pDataBuf->cEntriesLeft, pDataBuf->cbValid));
+                    Log(("vboxSfOs2ReadDirEntries: vboxSfOs2HostReqListDir failed %Rrc (%d,%d)\n", vrc,
+                         pDataBuf->Req.Parms.c32Entries.u.value32, pDataBuf->Req.Parms.cb32Buffer.u.value32));
                 pDataBuf->pEntry       = NULL;
                 pDataBuf->cEntriesLeft = 0;
+                pDataBuf->cbValid      = 0;
                 if (cMatches == 0)
                 {
@@ -411,12 +415,17 @@
         {
             pDataBuf->pEntry = pEntry = (PSHFLDIRINFO)&pEntry->name.String.utf8[pEntry->name.u16Size];
-            uintptr_t offEntry = (uintptr_t)pEntry - (uintptr_t)(pDataBuf + 1);
+            uintptr_t offEntry = (uintptr_t)pEntry - (uintptr_t)pDataBuf->pBuf;
             AssertMsgReturn(offEntry + RT_UOFFSETOF(SHFLDIRINFO, name.String) <= pDataBuf->cbValid,
                             ("offEntry=%#x cbValid=%#x\n", offEntry, pDataBuf->cbValid), ERROR_SYS_INTERNAL);
+            //Log(("next entry: %p / %#x: u16Size=%#x => size: %#x\n", pEntry, offEntry, RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size));
             AssertMsgReturn(offEntry + RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size <= pDataBuf->cbValid,
-                            ("offEntry=%#x cbValid=%#x\n", offEntry, pDataBuf->cbValid), ERROR_SYS_INTERNAL);
+                            ("offEntry=%#x + offName=%#x + cbName=%#x => %#x; cbValid=%#x\n",
+                             offEntry, RT_UOFFSETOF(SHFLDIRINFO, name.String), pEntry->name.u16Size,
+                             offEntry + RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size, pDataBuf->cbValid),
+                            ERROR_SYS_INTERNAL);
+            //Log(("%.*Rhxd\n", RT_UOFFSETOF(SHFLDIRINFO, name.String) + pEntry->name.u16Size, pEntry));
         }
         else
-            pDataBuf->pEntry = NULL;
+            pDataBuf->pEntry = pEntry = NULL;
     }
 
@@ -561,109 +570,120 @@
 
         /*
-         * Make sure we've got a buffer for keeping unused search results.
+         * Allocate data/request buffer and another buffer for receiving entries in.
          */
-        /** @todo use phys heap for this too?  */
-        PVBOXSFFSBUF pDataBuf = NULL;
         if (rc == NO_ERROR)
         {
-            pDataBuf = (PVBOXSFFSBUF)RTMemAlloc(cMaxMatches == 1 ? VBOXSFFSBUF_MIN_SIZE : _16K - ALLOC_HDR_SIZE);
+            PVBOXSFFSBUF pDataBuf = (PVBOXSFFSBUF)VbglR0PhysHeapAlloc(sizeof(*pDataBuf));
             if (pDataBuf)
-                pDataBuf->cbBuf = cMaxMatches == 1 ? VBOXSFFSBUF_MIN_SIZE : _16K - ALLOC_HDR_SIZE;
-            else
-            {
-                pDataBuf = (PVBOXSFFSBUF)RTMemAlloc(VBOXSFFSBUF_MIN_SIZE);
-                if (pDataBuf)
-                    pDataBuf->cbBuf = VBOXSFFSBUF_MIN_SIZE;
+            {
+#define MIN_BUF_SIZE (  RT_ALIGN_32(sizeof(SHFLDIRINFO) + CCHMAXPATHCOMP * sizeof(RTUTF16) + 64 /*fudge*/ + ALLOC_HDR_SIZE, 64) \
+                      - ALLOC_HDR_SIZE)
+                RT_ZERO(*pDataBuf);
+                pDataBuf->cbBuf = cMaxMatches == 1 ? MIN_BUF_SIZE : _16K - ALLOC_HDR_SIZE;
+                pDataBuf->pBuf  = (PSHFLDIRINFO)VbglR0PhysHeapAlloc(pDataBuf->cbBuf);
+                if (pDataBuf->pBuf)
+                { /* likely */ }
                 else
-                    rc = ERROR_NOT_ENOUGH_MEMORY;
-            }
-        }
-        if (rc == NO_ERROR)
-        {
-            /*
-             * Now, try open the directory for reading.
-             */
-            pReq->CreateParms.CreateFlags = SHFL_CF_DIRECTORY   | SHFL_CF_ACT_FAIL_IF_NEW  | SHFL_CF_ACT_OPEN_IF_EXISTS
-                                          | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
-
-            int vrc = vboxSfOs2HostReqCreate(pFolder, pReq);
-            LogFlow(("FS32_FINDFIRST: vboxSfOs2HostReqCreate(%ls) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
-                     pStrFolderPath->String.utf16, vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode,
-                     pReq->CreateParms.Handle));
-            if (RT_SUCCESS(vrc))
-            {
-                switch (pReq->CreateParms.Result)
                 {
-                    case SHFL_FILE_EXISTS:
-                        if (pReq->CreateParms.Handle != SHFL_HANDLE_NIL)
-                        {
-                            /*
-                             * Initialize the structures.
-                             */
-                            pFsFsd->hHostDir        = pReq->CreateParms.Handle;
-                            pFsFsd->u32Magic        = VBOXSFFS_MAGIC;
-                            pFsFsd->pFolder         = pFolder;
-                            pFsFsd->pBuf            = pDataBuf;
-                            pFsFsd->offLastFile     = 0;
-                            pDataBuf->u32Magic      = VBOXSFFSBUF_MAGIC;
-                            pDataBuf->cbValid       = 0;
-                            pDataBuf->cEntriesLeft  = 0;
-                            pDataBuf->pEntry        = NULL;
-                            pDataBuf->pFilter       = pFilter;
-                            pDataBuf->fMustHaveAttribs   = (uint8_t)((fAttribs >> 8) & (RTFS_DOS_MASK_OS2 >> RTFS_DOS_SHIFT));
-                            pDataBuf->fExcludedAttribs   = (uint8_t)(~fAttribs
-                                                                     & (  (RTFS_DOS_MASK_OS2 & ~(RTFS_DOS_ARCHIVED | RTFS_DOS_READONLY)
-                                                                        >> RTFS_DOS_SHIFT)));
-                            pDataBuf->fLongFilenames     = RT_BOOL(fAttribs & FF_ATTR_LONG_FILENAME);
-                            pDataBuf->cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
-
-                            rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags,
-                                                         pbData, cbData, cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
-                            if (rc == NO_ERROR)
+                    pDataBuf->pBuf = (PSHFLDIRINFO)VbglR0PhysHeapAlloc(MIN_BUF_SIZE);
+                    if (pDataBuf->pBuf)
+                        pDataBuf->cbBuf = MIN_BUF_SIZE;
+                    else
+                        rc = ERROR_NOT_ENOUGH_MEMORY;
+                }
+            }
+            if (rc == NO_ERROR)
+            {
+                /*
+                 * Now, try open the directory for reading.
+                 */
+                pReq->CreateParms.CreateFlags = SHFL_CF_DIRECTORY   | SHFL_CF_ACT_FAIL_IF_NEW  | SHFL_CF_ACT_OPEN_IF_EXISTS
+                                              | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
+
+                int vrc = vboxSfOs2HostReqCreate(pFolder, pReq);
+                LogFlow(("FS32_FINDFIRST: vboxSfOs2HostReqCreate(%ls) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
+                         pStrFolderPath->String.utf16, vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode,
+                         pReq->CreateParms.Handle));
+                if (RT_SUCCESS(vrc))
+                {
+                    switch (pReq->CreateParms.Result)
+                    {
+                        case SHFL_FILE_EXISTS:
+                            if (pReq->CreateParms.Handle != SHFL_HANDLE_NIL)
                             {
-                                uint32_t cRefs = ASMAtomicIncU32(&pFolder->cOpenSearches);
-                                Assert(cRefs < _4K); RT_NOREF(cRefs);
-
-                                /* We keep these on success: */
-                                if (pFilter == pStrFolderPath)
-                                    pStrFolderPath = NULL;
-                                pFilter  = NULL;
-                                pDataBuf = NULL;
-                                pFolder  = NULL;
+                                /*
+                                 * Initialize the structures.
+                                 */
+                                pFsFsd->hHostDir        = pReq->CreateParms.Handle;
+                                pFsFsd->u32Magic        = VBOXSFFS_MAGIC;
+                                pFsFsd->pFolder         = pFolder;
+                                pFsFsd->pBuf            = pDataBuf;
+                                pFsFsd->offLastFile     = 0;
+                                pDataBuf->u32Magic      = VBOXSFFSBUF_MAGIC;
+                                pDataBuf->cbValid       = 0;
+                                pDataBuf->cEntriesLeft  = 0;
+                                pDataBuf->pEntry        = NULL;
+                                pDataBuf->pFilter       = pFilter;
+                                pDataBuf->fMustHaveAttribs   = (uint8_t)((fAttribs >> 8) & (RTFS_DOS_MASK_OS2 >> RTFS_DOS_SHIFT));
+                                pDataBuf->fExcludedAttribs   = (uint8_t)(~fAttribs
+                                                                         & (  (RTFS_DOS_MASK_OS2 & ~(RTFS_DOS_ARCHIVED | RTFS_DOS_READONLY)
+                                                                            >> RTFS_DOS_SHIFT)));
+                                pDataBuf->fLongFilenames     = RT_BOOL(fAttribs & FF_ATTR_LONG_FILENAME);
+                                pDataBuf->cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
+
+                                rc = vboxSfOs2ReadDirEntries(pFolder, pFsFsd, pDataBuf, uLevel, fFlags,
+                                                             pbData, cbData, cMaxMatches ? cMaxMatches : UINT16_MAX, pcMatches);
+                                if (rc == NO_ERROR)
+                                {
+                                    uint32_t cRefs = ASMAtomicIncU32(&pFolder->cOpenSearches);
+                                    Assert(cRefs < _4K); RT_NOREF(cRefs);
+
+                                    /* We keep these on success: */
+                                    if (pFilter == pStrFolderPath)
+                                        pStrFolderPath = NULL;
+                                    pFilter  = NULL;
+                                    pDataBuf = NULL;
+                                    pFolder  = NULL;
+                                }
+                                else
+                                {
+                                    AssertCompile(sizeof(VBOXSFCLOSEREQ) < sizeof(*pReq));
+                                    vrc = vboxSfOs2HostReqClose(pFolder, (VBOXSFCLOSEREQ *)pReq, pFsFsd->hHostDir);
+                                    AssertRC(vrc);
+                                    pFsFsd->u32Magic = ~VBOXSFFS_MAGIC;
+                                    pDataBuf->u32Magic = ~VBOXSFFSBUF_MAGIC;
+                                    pFsFsd->pFolder  = NULL;
+                                    pFsFsd->hHostDir = NULL;
+                                }
                             }
                             else
                             {
-                                AssertCompile(sizeof(VBOXSFCLOSEREQ) < sizeof(*pReq));
-                                vrc = vboxSfOs2HostReqClose(pFolder, (VBOXSFCLOSEREQ *)pReq, pFsFsd->hHostDir);
-                                AssertRC(vrc);
-                                pFsFsd->u32Magic = ~VBOXSFFS_MAGIC;
-                                pDataBuf->u32Magic = ~VBOXSFFSBUF_MAGIC;
-                                pFsFsd->pFolder  = NULL;
-                                pFsFsd->hHostDir = NULL;
+                                LogFlow(("FS32_FINDFIRST: vboxSfOs2HostReqCreate returns NIL handle for '%ls'\n",
+                                         pStrFolderPath->String.utf16));
+                                rc = ERROR_PATH_NOT_FOUND;
                             }
-                        }
-                        else
-                        {
-                            LogFlow(("FS32_FINDFIRST: vboxSfOs2HostReqCreate returns NIL handle for '%ls'\n",
-                                     pStrFolderPath->String.utf16));
+                            break;
+
+                        case SHFL_PATH_NOT_FOUND:
                             rc = ERROR_PATH_NOT_FOUND;
-                        }
-                        break;
-
-                    case SHFL_PATH_NOT_FOUND:
-                        rc = ERROR_PATH_NOT_FOUND;
-                        break;
-
-                    default:
-                    case SHFL_FILE_NOT_FOUND:
-                        rc = ERROR_FILE_NOT_FOUND;
-                        break;
+                            break;
+
+                        default:
+                        case SHFL_FILE_NOT_FOUND:
+                            rc = ERROR_FILE_NOT_FOUND;
+                            break;
+                    }
                 }
-            }
-            else
-                rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
+                else
+                    rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_GEN_FAILURE);
+            }
+
+            if (pDataBuf)
+            {
+                VbglR0PhysHeapFree(pDataBuf->pBuf);
+                pDataBuf->pBuf = NULL;
+                VbglR0PhysHeapFree(pDataBuf);
+            }
         }
-
-        RTMemFree(pDataBuf);
         vboxSfOs2StrFree(pFilter);
         VbglR0PhysHeapFree(pReq);
@@ -818,5 +838,8 @@
     pDataBuf->u32Magic = ~VBOXSFFSBUF_MAGIC;
     pDataBuf->cbBuf    = 0;
-    RTMemFree(pDataBuf);
+
+    VbglR0PhysHeapFree(pDataBuf->pBuf);
+    pDataBuf->pBuf = NULL;
+    VbglR0PhysHeapFree(pDataBuf);
 
     uint32_t cRefs = ASMAtomicDecU32(&pFolder->cOpenSearches);
Index: /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInit.cpp
===================================================================
--- /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInit.cpp	(revision 76664)
+++ /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInit.cpp	(revision 76665)
@@ -102,6 +102,11 @@
                 if (RT_FAILURE(rc))
                     RTLogBackdoorPrintf("VBoxSFR0Init: Missing VBoxGuest.sys IDC connection!  Check order in Config.kmk!\n");
-                else if (!(fFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS))
-                    RTLogBackdoorPrintf("VBoxSFR0Init: Embedded buffers feature is missing.  Upgrade to latest VirtualBox!\n");
+                else
+                {
+                    if (!(fFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS))
+                        RTLogBackdoorPrintf("VBoxSFR0Init: WARNING! Embedded buffers feature is missing.  Upgrade to latest VirtualBox!\n");
+                    if (!(fFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST))
+                        RTLogBackdoorPrintf("VBoxSFR0Init: WARNING! Contiguous page list buffers feature is missing.  Upgrade to latest VirtualBox!\n");
+                }
 
                 /*
Index: /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h
===================================================================
--- /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h	(revision 76664)
+++ /trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h	(revision 76665)
@@ -157,15 +157,29 @@
 
 
-/**
- * VBoxSF File Search Buffer (header).
- */
-typedef struct VBOXSFFSBUF
-{
+/** Request structure for vboxSfOs2HostReqListDir. */
+typedef struct VBOXSFLISTDIRREQ
+{
+    VBGLIOCIDCHGCMFASTCALL  Hdr;
+    VMMDevHGCMCall          Call;
+    VBoxSFParmList          Parms;
+    HGCMPageListInfo        StrPgLst;
+    HGCMPageListInfo        BufPgLst;
+} VBOXSFLISTDIRREQ;
+
+/**
+ * More file search data (on physical heap).
+ */
+typedef struct VBOXSFFSBUF /**< @todo rename as is no longer buffer. */
+{
+    /** The request (must be first). */
+    VBOXSFLISTDIRREQ    Req;
     /** A magic number (VBOXSFFSBUF_MAGIC). */
     uint32_t            u32Magic;
-    /** Amount of buffer space allocated after this header. */
-    uint32_t            cbBuf;
     /** The filter string (full path), NULL if all files are request. */
     PSHFLSTRING         pFilter;
+    /** Size of the buffer for directory entries. */
+    uint32_t            cbBuf;
+    /** Buffer for directory entries on the physical heap. */
+    PSHFLDIRINFO        pBuf;
     /** Must have attributes (shifted down DOS attributes).  */
     uint8_t             fMustHaveAttribs;
@@ -184,15 +198,12 @@
     /** The next entry. */
     PSHFLDIRINFO        pEntry;
+    //uint32_t            uPadding3;
     /** Staging area for staging a full FILEFINDBUF4L (+ 32 safe bytes). */
     uint8_t             abStaging[RT_ALIGN_32(sizeof(FILEFINDBUF4L) + 32, 8)];
 } VBOXSFFSBUF;
-AssertCompileSizeAlignment(VBOXSFFSBUF, 8);
 /** Pointer to a file search buffer. */
 typedef VBOXSFFSBUF *PVBOXSFFSBUF;
 /** Magic number for VBOXSFFSBUF (Robert Anson Heinlein). */
 #define VBOXSFFSBUF_MAGIC       UINT32_C(0x19070707)
-/** Minimum buffer size. */
-#define VBOXSFFSBUF_MIN_SIZE (  RT_ALIGN_32(sizeof(VBOXSFFSBUF) + sizeof(SHFLDIRINFO) + CCHMAXPATHCOMP * 4 + ALLOC_HDR_SIZE, 64) \
-                              - ALLOC_HDR_SIZE)
 
 
@@ -878,5 +889,5 @@
     pReq->Parms.pBuf.type                   = VMMDevHGCMParmType_PageList;
     pReq->Parms.pBuf.u.PageList.size        = cbToRead;
-    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFREADPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     pReq->PgLst.flags                       = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     pReq->PgLst.cPages                      = (uint16_t)cPages;
@@ -960,13 +971,13 @@
     pReq->Parms.u64Handle.u.value64         = hHostFile;
 
-    pReq->Parms.off64Write.type              = VMMDevHGCMParmType_64bit;
-    pReq->Parms.off64Write.u.value64         = offWrite;
-
-    pReq->Parms.cb32Write.type               = VMMDevHGCMParmType_32bit;
-    pReq->Parms.cb32Write.u.value32          = cbToWrite;
+    pReq->Parms.off64Write.type             = VMMDevHGCMParmType_64bit;
+    pReq->Parms.off64Write.u.value64        = offWrite;
+
+    pReq->Parms.cb32Write.type              = VMMDevHGCMParmType_32bit;
+    pReq->Parms.cb32Write.u.value32         = cbToWrite;
 
     pReq->Parms.pBuf.type                   = VMMDevHGCMParmType_PageList;
     pReq->Parms.pBuf.u.PageList.size        = cbToWrite;
-    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->Parms.pBuf.u.PageList.offset      = RT_UOFFSETOF(VBOXSFWRITEPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     pReq->PgLst.flags                       = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     pReq->PgLst.cPages                      = (uint16_t)cPages;
@@ -982,4 +993,67 @@
 
 
+/**
+ * SHFL_FN_LIST request with separate string buffer and buffers for entries,
+ * both allocated on the physical heap.
+ */
+DECLINLINE(int) vboxSfOs2HostReqListDir(PVBOXSFFOLDER pFolder, VBOXSFLISTDIRREQ *pReq, uint64_t hHostDir,
+                                        PSHFLSTRING pFilter, uint32_t fFlags, PSHFLDIRINFO pBuffer, uint32_t cbBuffer)
+{
+    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+                                SHFL_FN_LIST, SHFL_CPARMS_LIST, sizeof(*pReq));
+
+    pReq->Parms.id32Root.type                   = VMMDevHGCMParmType_32bit;
+    pReq->Parms.id32Root.u.value32              = pFolder->hHostFolder.root;
+
+    pReq->Parms.u64Handle.type                  = VMMDevHGCMParmType_64bit;
+    pReq->Parms.u64Handle.u.value64             = hHostDir;
+
+    pReq->Parms.f32Flags.type                   = VMMDevHGCMParmType_32bit;
+    pReq->Parms.f32Flags.u.value32              = fFlags;
+
+    pReq->Parms.cb32Buffer.type                 = VMMDevHGCMParmType_32bit;
+    pReq->Parms.cb32Buffer.u.value32            = cbBuffer;
+
+    pReq->Parms.pStrFilter.type                 = VMMDevHGCMParmType_ContiguousPageList;
+    pReq->Parms.pStrFilter.u.PageList.offset    = RT_UOFFSETOF(VBOXSFLISTDIRREQ, StrPgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->StrPgLst.flags                        = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+    pReq->StrPgLst.cPages                       = 1;
+    if (pFilter)
+    {
+        pReq->Parms.pStrFilter.u.PageList.size  = SHFLSTRING_HEADER_SIZE + pFilter->u16Size;
+        RTGCPHYS32 const GCPhys       = VbglR0PhysHeapGetPhysAddr(pFilter);
+        uint32_t const   offFirstPage = GCPhys & PAGE_OFFSET_MASK;
+        pReq->StrPgLst.offFirstPage             = (uint16_t)offFirstPage;
+        pReq->StrPgLst.aPages[0]                = GCPhys - offFirstPage;
+    }
+    else
+    {
+        pReq->Parms.pStrFilter.u.PageList.size  = 0;
+        pReq->StrPgLst.offFirstPage             = 0;
+        pReq->StrPgLst.aPages[0]                = NIL_RTGCPHYS64;
+    }
+
+    pReq->Parms.pBuffer.type                    = VMMDevHGCMParmType_ContiguousPageList;
+    pReq->Parms.pBuffer.u.PageList.offset       = RT_UOFFSETOF(VBOXSFLISTDIRREQ, BufPgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->Parms.pBuffer.u.PageList.size         = cbBuffer;
+    pReq->BufPgLst.flags                        = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+    pReq->BufPgLst.cPages                       = 1;
+    RTGCPHYS32 const GCPhys       = VbglR0PhysHeapGetPhysAddr(pBuffer);
+    uint32_t const   offFirstPage = GCPhys & PAGE_OFFSET_MASK;
+    pReq->BufPgLst.offFirstPage                 = (uint16_t)offFirstPage;
+    pReq->BufPgLst.aPages[0]                    = GCPhys - offFirstPage;
+
+    pReq->Parms.f32Done.type                    = VMMDevHGCMParmType_32bit;
+    pReq->Parms.f32Done.u.value32               = 0;
+
+    pReq->Parms.c32Entries.type                 = VMMDevHGCMParmType_32bit;
+    pReq->Parms.c32Entries.u.value32            = 0;
+
+    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+    if (RT_SUCCESS(vrc))
+        vrc = pReq->Call.header.result;
+    return vrc;
+}
+
 /** @} */
 
