Index: trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp
===================================================================
--- trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp	(revision 76105)
+++ trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp	(revision 76108)
@@ -189,19 +189,22 @@
 
 /**
- * Allocates a SHFLSTRING buffer.
+ * Allocates a SHFLSTRING buffer (UTF-16).
  *
  * @returns Pointer to a SHFLSTRING buffer, NULL if out of memory.
- * @param   cchLength   The desired string buffer length (excluding terminator).
- */
-PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength)
-{
-    AssertReturn(cchLength <= 0x1000, NULL);
-
-    PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchLength + 1);
+ * @param   cwcLength   The desired string buffer length in UTF-16 units
+ *                      (excluding terminator).
+ */
+PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength)
+{
+    AssertReturn(cwcLength <= 0x1000, NULL);
+    uint16_t cb = (uint16_t)cwcLength + 1;
+    cb *= sizeof(RTUTF16);
+
+    PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cb);
     if (pStr)
     {
-        pStr->u16Size       = (uint16_t)(cchLength + 1);
-        pStr->u16Length     = 0;
-        pStr->String.ach[0] = '\0';
+        pStr->u16Size         = cb;
+        pStr->u16Length       = 0;
+        pStr->String.utf16[0] = '\0';
         return pStr;
     }
@@ -211,26 +214,20 @@
 
 /**
- * Duplicates a UTF-8 string into a SHFLSTRING buffer.
+ * Duplicates a shared folders string buffer (UTF-16).
  *
  * @returns Pointer to a SHFLSTRING buffer containing the copy.
  *          NULL if out of memory or the string is too long.
- * @param   pachSrc     The string to clone.
- * @param   cchSrc      The length of the substring, RTMAX_STR for the whole.
- */
-PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc)
-{
-    if (cchSrc == RTSTR_MAX)
-        cchSrc = strlen(pachSrc);
-    if (cchSrc < 0x1000)
-    {
-        PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchSrc + 1);
-        if (pStr)
-        {
-            pStr->u16Size  = (uint16_t)(cchSrc + 1);
-            pStr->u16Length = (uint16_t)cchSrc;
-            memcpy(pStr->String.ach, pachSrc, cchSrc);
-            pStr->String.ach[cchSrc] = '\0';
-            return pStr;
-        }
+ * @param   pSrc        The string to clone.
+ */
+PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc)
+{
+    PSHFLSTRING pDst = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Length + sizeof(RTUTF16));
+    if (pDst)
+    {
+        pDst->u16Size   = pSrc->u16Length + (uint16_t)sizeof(RTUTF16);
+        pDst->u16Length = pSrc->u16Length;
+        memcpy(&pDst->String, &pSrc->String, pSrc->u16Length);
+        pDst->String.utf16[pSrc->u16Length / sizeof(RTUTF16)] = '\0';
+        return pDst;
     }
     return NULL;
@@ -268,14 +265,5 @@
     int rc = VbglR0SfConnect(&g_SfClient);
     if (RT_SUCCESS(rc))
-    {
-        rc = VbglR0SfSetUtf8(&g_SfClient);
-        if (RT_SUCCESS(rc))
-            g_fIsConnectedToService = true;
-        else
-        {
-            LogRel(("VbglR0SfSetUtf8 failed: %Rrc\n", rc));
-            VbglR0SfDisconnect(&g_SfClient);
-        }
-    }
+        g_fIsConnectedToService = true;
     else
         LogRel(("VbglR0SfConnect failed: %Rrc\n", rc));
@@ -358,5 +346,7 @@
  *
  * @returns VBox status code.
- * @param   pName       The name of the folder to map.
+ * @param   pName       The name of the folder to map - ASCII (not UTF-16!).
+ *                      Must be large enough to hold UTF-16 expansion of the
+ *                      string, will do so upon return.
  * @param   pszTag      Folder tag (for the VBoxService automounter).  Optional.
  * @param   ppFolder    Where to return the folder structure on success.
@@ -386,4 +376,15 @@
             memcpy(&pNew->szName[pName->u16Length + 1], pszTag, cbTag);
 
+        /* Expand the folder name to UTF-16. */
+        uint8_t                 off     = pNew->cchName;
+        uint8_t volatile const *pbSrc   = &pName->String.utf8[0];
+        RTUTF16 volatile       *pwcDst  = &pName->String.utf16[0];
+        do
+            pwcDst[off] = pbSrc[off];
+        while (off-- > 0);
+        pName->u16Length *= sizeof(RTUTF16);
+        Assert(pName->u16Length + sizeof(RTUTF16) <= pName->u16Size);
+
+        /* Try do the mapping.*/
         rc = VbglR0SfMapFolder(&g_SfClient, pName, &pNew->hHostFolder);
         if (RT_SUCCESS(rc))
@@ -397,5 +398,5 @@
         else
         {
-            LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%.*s,) -> %Rrc\n", pName->u16Length, pName->String.utf8, rc));
+            LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%s,) -> %Rrc\n", pNew->szName, rc));
             RTMemFree(pNew);
         }
@@ -465,5 +466,5 @@
 
 /**
- * Converts a path to UTF-8 and puts it in a VBGL friendly buffer.
+ * Converts a path to UTF-16 and puts it in a VBGL friendly buffer.
  *
  * @returns OS/2 status code
@@ -474,5 +475,7 @@
 APIRET vboxSfOs2ConvertPath(const char *pszFolderPath, PSHFLSTRING *ppStr)
 {
-    /* Skip unnecessary leading slashes. */
+    /*
+     * Skip unnecessary leading slashes.
+     */
     char ch = *pszFolderPath;
     if (ch == '\\' || ch == '/')
@@ -480,17 +483,124 @@
             pszFolderPath++;
 
-    /** @todo do proper codepage -> utf8 conversion and straighten out
-     *        everything... */
+    /*
+     * Since the KEE unicode conversion routines does not seem to know of
+     * surrogate pairs, we will get a very good output size estimate by
+     * using strlen() on the input.
+     */
     size_t cchSrc = strlen(pszFolderPath);
-    PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc);
+    PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc + 4 /*fudge*/);
     if (pDst)
     {
-        pDst->u16Length = (uint16_t)cchSrc;
-        memcpy(pDst->String.utf8, pszFolderPath, cchSrc);
-        pDst->String.utf8[cchSrc] = '\0';
-        *ppStr = pDst;
-        return NO_ERROR;
-    }
+        APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
+        if (rc == NO_ERROR)
+        {
+            pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
+            *ppStr = pDst;
+            return NO_ERROR;
+        }
+        VbglR0PhysHeapFree(pDst);
+
+        /*
+         * This shouldn't happen, but just in case we try again with
+         * twice the buffer size.
+         */
+        if (rc == 0x20412 /*ULS_BUFFERFULL*/)
+        {
+            pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2);
+            if (pDst)
+            {
+                rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
+                if (rc == NO_ERROR)
+                {
+                    pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
+                    *ppStr = pDst;
+                    return NO_ERROR;
+                }
+                VbglR0PhysHeapFree(pDst);
+                LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
+            }
+        }
+        else
+            LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
+    }
+
+    LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x\n", cchSrc));
     *ppStr = NULL;
+    return ERROR_NOT_ENOUGH_MEMORY;
+}
+
+
+/**
+ * Converts a path to UTF-16 and puts it in a VBGL friendly buffer within a
+ * larger buffer.
+ *
+ * @returns OS/2 status code
+ * @param   pszFolderPath   The path to convert.
+ * @param   offStrInBuf     The offset of the SHLFSTRING in the return buffer.
+ *                          This first part of the buffer is zeroed.
+ * @param   ppvBuf          Where to return the pointer to the buffer.  Free
+ *                          using vboxSfOs2FreePath.
+ */
+APIRET vboxSfOs2ConvertPathEx(const char *pszFolderPath, uint32_t offStrInBuf, void **ppvBuf)
+{
+    /*
+     * Skip unnecessary leading slashes.
+     */
+    char ch = *pszFolderPath;
+    if (ch == '\\' || ch == '/')
+        while ((ch = pszFolderPath[1]) == '\\' || ch == '/')
+            pszFolderPath++;
+
+    /*
+     * Since the KEE unicode conversion routines does not seem to know of
+     * surrogate pairs, we will get a very good output size estimate by
+     * using strlen() on the input.
+     */
+    size_t cchSrc = strlen(pszFolderPath);
+    void *pvBuf = VbglR0PhysHeapAlloc(offStrInBuf + SHFLSTRING_HEADER_SIZE + (cchSrc + 4) * sizeof(RTUTF16));
+    if (pvBuf)
+    {
+        RT_BZERO(pvBuf, offStrInBuf);
+
+        PSHFLSTRING pDst = (PSHFLSTRING)((uint8_t *)pvBuf + offStrInBuf);
+        APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
+        if (rc == NO_ERROR)
+        {
+            pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
+            pDst->u16Size   = (uint16_t)((cchSrc + 4) * sizeof(RTUTF16));
+            Assert(pDst->u16Length < pDst->u16Size);
+            *ppvBuf = pvBuf;
+            return NO_ERROR;
+        }
+        VbglR0PhysHeapFree(pvBuf);
+
+#if 0
+        /*
+         * This shouldn't happen, but just in case we try again with
+         * twice the buffer size.
+         */
+        if (rc == 0x20412 /*ULS_BUFFERFULL*/)
+        {
+            pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2);
+            if (pDst)
+            {
+                rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
+                if (rc == NO_ERROR)
+                {
+                    pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
+                    *ppStr = pDst;
+                    return NO_ERROR;
+                }
+                VbglR0PhysHeapFree(pDst);
+                LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
+            }
+        }
+        else
+#endif
+            LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
+    }
+
+    LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x offStrInBuf=%#x\n", cchSrc, offStrInBuf));
+    *ppvBuf = NULL;
     return ERROR_NOT_ENOUGH_MEMORY;
 }
@@ -553,7 +663,11 @@
          * Copy the name into the buffer format that Vbgl desires.
          */
-        PSHFLSTRING pStrName = vboxSfOs2StrDup(pachFolderName, cchFolderName);
+        PSHFLSTRING pStrName = vboxSfOs2StrAlloc(cchFolderName);
         if (pStrName)
         {
+            memcpy(pStrName->String.ach, pachFolderName, cchFolderName);
+            pStrName->String.ach[cchFolderName] = '\0';
+            pStrName->u16Length = (uint16_t)cchFolderName;
+
             /*
              * Do the attaching.
@@ -692,4 +806,135 @@
                  */
                 rc = vboxSfOs2ConvertPath(&pszPath[3], ppStrFolderPath);
+                if (rc == NO_ERROR)
+                    return rc;
+
+                vboxSfOs2ReleaseFolder(pFolder);
+                *ppFolder = NULL;
+                return rc;
+            }
+            KernReleaseSharedMutex(&g_MtxFolders);
+            LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath));
+            return ERROR_PATH_NOT_FOUND;
+        }
+        LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath));
+        return ERROR_PATH_NOT_FOUND;
+    }
+    LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
+    RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd);
+    return ERROR_PATH_NOT_FOUND;
+}
+
+
+/**
+ * Resolves the given path to a folder structure and folder relative string,
+ * the latter placed within a larger request buffer.
+ *
+ * @returns OS/2 status code.
+ * @param   pszPath         The path to resolve.
+ * @param   pCdFsd          The IFS dependent CWD structure if present.
+ * @param   offCurDirEnd    The offset into @a pszPath of the CWD.  -1 if not
+ *                          CWD relative path.
+ * @param   offStrInBuf     The offset of the SHLFSTRING in the return buffer.
+ *                          This first part of the buffer is zeroed.
+ * @param   ppFolder        Where to return the referenced pointer to the folder
+ *                          structure.  Call vboxSfOs2ReleaseFolder() when done.
+ * @param   ppvBuf          Where to return the Pointer to the buffer.  Free
+ *                          using VbglR0PhysHeapFree.
+ */
+APIRET vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf,
+                              PVBOXSFFOLDER *ppFolder, void **ppvBuf)
+{
+    APIRET rc;
+
+    /*
+     * UNC path?  Reject the prefix to be on the safe side.
+     */
+    char ch = pszPath[0];
+    if (ch == '\\' || ch == '/')
+    {
+        size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath);
+        if (cchPrefix > 0)
+        {
+            /* Find the length of the folder name (share). */
+            const char *pszFolderName = &pszPath[cchPrefix];
+            size_t      cchFolderName = 0;
+            while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/')
+            {
+                if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':')
+                    cchFolderName++;
+                else
+                {
+                    LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n",
+                            cchPrefix + cchFolderName, strlen(pszPath), pszPath));
+                    return ERROR_INVALID_NAME;
+                }
+            }
+            if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME)
+            {
+                LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n",
+                        cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath));
+                return ERROR_FILENAME_EXCED_RANGE;
+            }
+
+            /*
+             * Look for the share.
+             */
+            KernRequestSharedMutex(&g_MtxFolders);
+            PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName);
+            if (pFolder)
+            {
+                vboxSfOs2RetainFolder(pFolder);
+                KernReleaseSharedMutex(&g_MtxFolders);
+            }
+            else
+            {
+                uint32_t const uRevBefore = g_uFolderRevision;
+                KernReleaseSharedMutex(&g_MtxFolders);
+                rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder);
+                if (rc == NO_ERROR)
+                    pFolder = *ppFolder;
+                else
+                    return rc;
+            }
+
+            /*
+             * Convert the path and put it in a Vbgl compatible buffer..
+             */
+            rc = vboxSfOs2ConvertPathEx(&pszFolderName[cchFolderName], offStrInBuf, ppvBuf);
+            if (rc == NO_ERROR)
+                return rc;
+
+            vboxSfOs2ReleaseFolder(pFolder);
+            *ppFolder = NULL;
+            return rc;
+        }
+
+        LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
+        return ERROR_PATH_NOT_FOUND;
+    }
+
+    /*
+     * Drive letter?
+     */
+    ch &= ~0x20; /* upper case */
+    if (   ch >= 'A'
+        && ch <= 'Z'
+        && pszPath[1] == ':')
+    {
+        unsigned iDrive = ch - 'A';
+        ch  = pszPath[2];
+        if (ch == '\\' || ch == '/')
+        {
+            KernRequestSharedMutex(&g_MtxFolders);
+            PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive];
+            if (pFolder)
+            {
+                vboxSfOs2RetainFolder(pFolder);
+                KernReleaseSharedMutex(&g_MtxFolders);
+
+                /*
+                 * Convert the path and put it in a Vbgl compatible buffer..
+                 */
+                rc = vboxSfOs2ConvertPathEx(&pszPath[3], offStrInBuf, ppvBuf);
                 if (rc == NO_ERROR)
                     return rc;
@@ -1006,5 +1251,5 @@
     RT_NOREF(uType); /* pass 1 or pass 2 doesn't matter to us, we've only got one 'server'. */
 
-    if (vboxSfOs2UncPrefixLength(pszName) > 0 )
+    if (vboxSfOs2UncPrefixLength(pszName) > 0)
         return NO_ERROR;
     return ERROR_NOT_SUPPORTED;
@@ -1074,5 +1319,5 @@
                 {
                     SHFLSTRING Path;
-                    uint8_t    abPadding[SHFLSTRING_HEADER_SIZE + 4];
+                    uint8_t    abPadding[SHFLSTRING_HEADER_SIZE + 4 * sizeof(RTUTF16)];
                 };
             } Open;
@@ -1096,9 +1341,9 @@
         pu->Open.Params.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;
-        pu->Open.Path.u16Size   = 3;
-        pu->Open.Path.u16Length = 2;
-        pu->Open.Path.String.utf8[0] = '\\';
-        pu->Open.Path.String.utf8[1] = '.';
-        pu->Open.Path.String.utf8[2] = '\0';
+        pu->Open.Path.u16Size   = 3 * sizeof(RTUTF16);
+        pu->Open.Path.u16Length = 2 * sizeof(RTUTF16);
+        pu->Open.Path.String.utf16[0] = '\\';
+        pu->Open.Path.String.utf16[1] = '.';
+        pu->Open.Path.String.utf16[2] = '\0';
 
         int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, &pu->Open.Path, &pu->Open.Params);
@@ -1272,4 +1517,5 @@
 {
     LogFlow(("FS32_MKDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} pEAOp=%p fFlags=%#x\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd, pEaOp, fFlags));
+    RT_NOREF(fFlags);
 
     /*
@@ -1626,5 +1872,5 @@
     LogFlow(("FS32_FILEATTRIBUTE: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pfAttr=%p\n",
              fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszName, pszName, offCurDirEnd, pfAttr));
-    RT_NOREF(offCurDirEnd);
+    RT_NOREF(pCdFsi, offCurDirEnd);
 
     APIRET rc;
Index: trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp
===================================================================
--- trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp	(revision 76105)
+++ trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp	(revision 76108)
@@ -50,5 +50,5 @@
     LogFlow(("FS32_OPENCREATE: pCdFsi=%p pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pSfFsi=%p pSfFsd=%p fOpenMode=%#x fOpenFlags=%#x puAction=%p fAttribs=%#x pbEaBuf=%p pfGenFlag=%p\n",
              pCdFsi, pCdFsd, pszName, pszName, offCurDirEnd, pSfFsi, pSfFsd, fOpenMode, fOpenFlags, puAction, fAttribs, pbEaBuf, pfGenFlag));
-    RT_NOREF(pfGenFlag);
+    RT_NOREF(pfGenFlag, pCdFsi);
 
     /*
@@ -73,28 +73,39 @@
     }
 
-    SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
-    if (!pParams)
-        return ERROR_NOT_ENOUGH_MEMORY;
-    RT_ZERO(*pParams);
-
+    /*
+     * Allocate request buffer and resovle the path to folder and folder relative path.
+     */
+    PVBOXSFFOLDER       pFolder;
+    VBOXSFCREATEREQ    *pReq;
+    APIRET rc = vboxSfOs2ResolvePathEx(pszName, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
+                                       &pFolder, (void **)&pReq);
+    LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
+    if (rc == NO_ERROR)
+    { /* likely */ }
+    else
+        return rc;
+
+    /*
+     * Continue validating and converting parameters.
+     */
     /* access: */
     if (fOpenMode & OPEN_ACCESS_READWRITE)
-        pParams->CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
+        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
     else if (fOpenMode & OPEN_ACCESS_WRITEONLY)
-        pParams->CreateFlags = SHFL_CF_ACCESS_WRITE     | SHFL_CF_ACCESS_ATTR_WRITE;
+        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_WRITE     | SHFL_CF_ACCESS_ATTR_WRITE;
     else
-        pParams->CreateFlags = SHFL_CF_ACCESS_READ      | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
+        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READ      | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
 
     /* Sharing: */
     switch (fOpenMode & (OPEN_SHARE_DENYNONE | OPEN_SHARE_DENYREADWRITE | OPEN_SHARE_DENYREAD | OPEN_SHARE_DENYWRITE))
     {
-        case OPEN_SHARE_DENYNONE:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
-        case OPEN_SHARE_DENYWRITE:      pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
-        case OPEN_SHARE_DENYREAD:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
-        case OPEN_SHARE_DENYREADWRITE:  pParams->CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
-        case 0:                         pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
+        case OPEN_SHARE_DENYNONE:       pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
+        case OPEN_SHARE_DENYWRITE:      pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
+        case OPEN_SHARE_DENYREAD:       pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
+        case OPEN_SHARE_DENYREADWRITE:  pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
+        case 0:                         pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
         default:
             LogRel(("FS32_OPENCREATE: Invalid file sharing mode: %#x\n", fOpenMode));
-            VbglR0PhysHeapFree(pParams);
+            VbglR0PhysHeapFree(pReq);
             return VERR_INVALID_PARAMETER;
 
@@ -104,25 +115,25 @@
     switch (fOpenFlags & 0x13)
     {
-        case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x00 */
-            pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+        case                                 OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x00 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
             break;
-        case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x10 */
-            pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        case                                 OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x10 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
             break;
-        case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x01 */
-            pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+        case                                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x01 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
             break;
-        case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x11 */
-            pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        case                                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x11 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
             break;
-        case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:   /* 0x02 */
-            pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
+        case                                 OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:   /* 0x02 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
             break;
-        case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
-            pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
+        case                                 OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
+            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
             break;
         default:
             LogRel(("FS32_OPENCREATE: Invalid file open flags: %#x\n", fOpenFlags));
-            VbglR0PhysHeapFree(pParams);
+            VbglR0PhysHeapFree(pReq);
             return VERR_INVALID_PARAMETER;
     }
@@ -131,94 +142,83 @@
 
     /* Attributes: */
-    pParams->Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
+    pReq->CreateParms.Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
 
     /* Initial size: */
     if (pSfFsi->sfi_sizel > 0)
-        pParams->Info.cbObject = pSfFsi->sfi_sizel;
-
-    /*
-     * Resolve path to a folder and folder relative path.
-     */
-    PVBOXSFFOLDER pFolder;
-    PSHFLSTRING   pStrFolderPath;
-    RT_NOREF(pCdFsi);
-    APIRET rc = vboxSfOs2ResolvePath(pszName, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
-    LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
-    if (rc == NO_ERROR)
-    {
-        /*
-         * Try open the file.
-         */
-        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
-        LogFlow(("FS32_OPENCREATE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
-        if (RT_SUCCESS(vrc))
+        pReq->CreateParms.Info.cbObject = pSfFsi->sfi_sizel;
+
+    /*
+     * Try open the file.
+     */
+    int vrc = vboxSfOs2HostReqCreate(pFolder, pReq);
+    LogFlow(("FS32_OPENCREATE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
+    if (RT_SUCCESS(vrc))
+    {
+        switch (pReq->CreateParms.Result)
         {
-            switch (pParams->Result)
-            {
-                case SHFL_FILE_EXISTS:
-                    if (pParams->Handle == SHFL_HANDLE_NIL)
-                    {
-                        rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
-                        break;
-                    }
-                    RT_FALL_THRU();
-                case SHFL_FILE_CREATED:
-                case SHFL_FILE_REPLACED:
-                    if (   pParams->Info.cbObject < _2G
-                        || (fOpenMode & OPEN_FLAGS_LARGEFILE))
-                    {
-                        pSfFsd->u32Magic    = VBOXSFSYFI_MAGIC;
-                        pSfFsd->pSelf       = pSfFsd;
-                        pSfFsd->hHostFile   = pParams->Handle;
-                        pSfFsd->pFolder     = pFolder;
-
-                        uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
-                        Assert(cOpenFiles < _32K);
-                        pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
-
-                        pSfFsi->sfi_sizel   = pParams->Info.cbObject;
-                        pSfFsi->sfi_type    = STYPE_FILE;
-                        pSfFsi->sfi_DOSattr = (uint8_t)((pParams->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
-                        int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
-                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pParams->Info.BirthTime,        cMinLocalTimeDelta);
-                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pParams->Info.AccessTime,       cMinLocalTimeDelta);
-                        vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pParams->Info.ModificationTime, cMinLocalTimeDelta);
-                        if (pParams->Result == SHFL_FILE_CREATED)
-                            pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
-
-                        *puAction = pParams->Result == SHFL_FILE_CREATED ? FILE_CREATED
-                                  : pParams->Result == SHFL_FILE_EXISTS  ? FILE_EXISTED
-                                  :                                        FILE_TRUNCATED;
-
-                        Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
-                        rc = NO_ERROR;
-                    }
-                    else
-                    {
-                        LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pParams->Info.cbObject, pszName));
-                        VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pParams->Handle);
-                        rc = ERROR_ACCESS_DENIED;
-                    }
+            case SHFL_FILE_EXISTS:
+                if (pReq->CreateParms.Handle == SHFL_HANDLE_NIL)
+                {
+                    rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
                     break;
-
-                case SHFL_PATH_NOT_FOUND:
-                    rc = ERROR_PATH_NOT_FOUND;
-                    break;
-
-                default:
-                case SHFL_FILE_NOT_FOUND:
-                    rc = ERROR_OPEN_FAILED;
-                    break;
-            }
+                }
+                RT_FALL_THRU();
+            case SHFL_FILE_CREATED:
+            case SHFL_FILE_REPLACED:
+                if (   pReq->CreateParms.Info.cbObject < _2G
+                    || (fOpenMode & OPEN_FLAGS_LARGEFILE))
+                {
+                    pSfFsd->u32Magic    = VBOXSFSYFI_MAGIC;
+                    pSfFsd->pSelf       = pSfFsd;
+                    pSfFsd->hHostFile   = pReq->CreateParms.Handle;
+                    pSfFsd->pFolder     = pFolder;
+
+                    uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
+                    Assert(cOpenFiles < _32K);
+                    pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
+
+                    pSfFsi->sfi_sizel   = pReq->CreateParms.Info.cbObject;
+                    pSfFsi->sfi_type    = STYPE_FILE;
+                    pSfFsi->sfi_DOSattr = (uint8_t)((pReq->CreateParms.Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
+                    int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
+                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->CreateParms.Info.BirthTime,        cMinLocalTimeDelta);
+                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->CreateParms.Info.AccessTime,       cMinLocalTimeDelta);
+                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->CreateParms.Info.ModificationTime, cMinLocalTimeDelta);
+                    if (pReq->CreateParms.Result == SHFL_FILE_CREATED)
+                        pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
+
+                    *puAction = pReq->CreateParms.Result == SHFL_FILE_CREATED ? FILE_CREATED
+                              : pReq->CreateParms.Result == SHFL_FILE_EXISTS  ? FILE_EXISTED
+                              :                                                 FILE_TRUNCATED;
+
+                    Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
+                    rc = NO_ERROR;
+                }
+                else
+                {
+                    LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pReq->CreateParms.Info.cbObject, pszName));
+                    VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pReq->CreateParms.Handle);
+                    rc = ERROR_ACCESS_DENIED;
+                }
+                break;
+
+            case SHFL_PATH_NOT_FOUND:
+                rc = ERROR_PATH_NOT_FOUND;
+                break;
+
+            default:
+            case SHFL_FILE_NOT_FOUND:
+                rc = ERROR_OPEN_FAILED;
+                break;
         }
-        else if (vrc == VERR_ALREADY_EXISTS)
-            rc = ERROR_ACCESS_DENIED;
-        else if (vrc == VERR_FILE_NOT_FOUND)
-            rc = ERROR_OPEN_FAILED;
-        else
-            rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
-        vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
-    }
-    VbglR0PhysHeapFree(pParams);
+    }
+    else if (vrc == VERR_ALREADY_EXISTS)
+        rc = ERROR_ACCESS_DENIED;
+    else if (vrc == VERR_FILE_NOT_FOUND)
+        rc = ERROR_OPEN_FAILED;
+    else
+        rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
+    VbglR0PhysHeapFree(pReq);
+    vboxSfOs2ReleaseFolder(pFolder);
     LogFlow(("FS32_OPENCREATE: returns %u\n", rc));
     return rc;
@@ -465,7 +465,4 @@
     return rc;
 }
-
-#include <VBox/VBoxGuest.h>
-
 
 
Index: trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp
===================================================================
--- trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp	(revision 76105)
+++ trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp	(revision 76108)
@@ -49,17 +49,17 @@
  *
  * @returns true if compatible, false if not.
- * @param   pszName     The name to inspect (UTF-8).
- * @param   cchName     The length of the name.
- * @param   pwszTmp     Buffer for test conversions.
- * @param   cwcTmp      The size of the buffer.
+ * @param   pwszName    The name to inspect (UTF-16).
+ * @param   cwcName     The length of the name.
+ * @param   pszTmp      Buffer for test conversions.
+ * @param   cbTmp       The size of the buffer.
  */
-static bool vboxSfOs2IsUtf8Name8dot3(const char *pszName, size_t cchName, PRTUTF16 pwszTmp, size_t cwcTmp)
-{
-    /* Reject names that must be too long when using maximum UTF-8 encoding. */
-    if (cchName > (8 + 1 + 3) * 4)
+static bool vboxSfOs2IsUtf16Name8dot3(PRTUTF16 pwszName, size_t cwcName, char *pszTmp, size_t cbTmp)
+{
+    /* Reject names that must be too long. */
+    if (cwcName > 8 + 1 + 3)
         return false;
 
-    /* First char cannot be a dot. */
-    if (*pszName == '.' || !*pszName)
+    /* First char cannot be a dot, nor can it be an empty string. */
+    if (*pwszName == '.' || !*pwszName)
         return false;
 
@@ -67,72 +67,62 @@
      * To basic checks on code point level before doing full conversion.
      */
-    const char *pszCursor = pszName;
-    for (uint32_t cuc = 0; ; cuc++)
-    {
-        RTUNICP uCp;
-        RTStrGetCpEx(&pszCursor, &uCp);
-        if (uCp == '.')
+    for (unsigned off = 0; ; off++)
+    {
+        RTUTF16 wc = pwszName[off];
+        if (wc == '.')
         {
-            for (cuc = 0; ; cuc++)
-            {
-                RTStrGetCpEx(&pszCursor, &uCp);
-                if (!uCp)
+            unsigned const offMax = off + 3;
+            for (++off;; off++)
+            {
+                wc = pwszName[off];
+                if (!wc)
                     break;
-                if (uCp == '.')
+                if (wc == '.')
                     return false;
-                if (cuc >= 3)
+                if (off >= offMax)
                     return false;
             }
             break;
         }
-        if (!uCp)
+        if (!wc)
             break;
-        if (cuc >= 8)
+        if (off >= 8)
             return false;
     }
 
     /*
-     * Convert to UTF-16 and then to native codepage.
-     */
-    size_t cwcActual = cwcTmp;
-    int rc = RTStrToUtf16Ex(pszName, cchName, &pwszTmp, cwcTmp, &cwcActual);
-    if (RT_SUCCESS(rc))
-    {
-        char *pszTmp = (char *)&pwszTmp[cwcActual + 1];
-        rc = KernStrFromUcs(NULL, pszTmp, pwszTmp, (cwcTmp - cwcActual - 1) * sizeof(RTUTF16), cwcActual);
-        if (rc != NO_ERROR)
-        {
-            LogRel(("vboxSfOs2IsUtf8Name8dot3: KernStrFromUcs failed: %d\n", rc));
+     * Conver to the native code page.
+     */
+    APIRET rc = KernStrFromUcs(NULL, pszTmp, pwszName, cbTmp, cwcName);
+    if (rc != NO_ERROR)
+    {
+        LogRel(("vboxSfOs2IsUtf8Name8dot3: KernStrFromUcs failed: %d\n", rc));
+        return false;
+    }
+
+    /*
+     * Redo the check.
+     * Note! This could be bogus if a DBCS leadin sequence collides with '.'.
+     */
+    for (unsigned cch = 0; ; cch++)
+    {
+        char ch = *pszTmp++;
+        if (ch == '.')
+            break;
+        if (ch == '\0')
+            return true;
+        if (cch >= 8)
             return false;
-        }
-
-        /*
-         * Redo the check.
-         * Note! This could be bogus if a DBCS leadin sequence collides with '.'.
-         */
-        for (uint32_t cch = 0; ; cch++)
-        {
-            char ch = *pszTmp++;
-            if (ch == '.')
-                break;
-            if (ch == '\0')
-                return true;
-            if (cch >= 8)
-                return false;
-        }
-        for (uint32_t cch = 0; ; cch++)
-        {
-            char ch = *pszTmp++;
-            if (ch == '\0')
-                return true;
-            if (ch != '.')
-                return false;
-            if (cch >= 3)
-                return false;
-        }
-    }
-    else
-        LogRel(("vboxSfOs2IsUtf8Name8dot3: RTStrToUtf16Ex failed: %Rrc\n", rc));
-    return false;
+    }
+    for (unsigned cch = 0; ; cch++)
+    {
+        char ch = *pszTmp++;
+        if (ch == '\0')
+            return true;
+        if (ch != '.')
+            return false;
+        if (cch >= 3)
+            return false;
+    }
 }
 
@@ -141,51 +131,17 @@
  * @returns Updated pbDst on success, NULL on failure.
  */
-static uint8_t *vboxSfOs2CopyUtf8Name(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
-{
-    /* Convert UTF-8 to UTF-16: */
-    int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
-    if (RT_SUCCESS(rc))
-    {
-        char *pszDst = (char *)(pbDst + 1);
-        rc = KernStrFromUcs(NULL, pszDst, pwszTmp, CCHMAXPATHCOMP, cwcTmp);
-        if (rc == NO_ERROR)
-        {
-            size_t cchDst = strlen(pszDst);
-            *pbDst++ = (uint8_t)cchDst;
-            pbDst   += cchDst;
-            *pbDst++ = '\0';
-            return pbDst;
-        }
-        LogRel(("vboxSfOs2CopyUtf8Name: KernStrFromUcs failed: %d\n", rc));
-    }
-    else
-        LogRel(("vboxSfOs2CopyUtf8Name: RTStrToUtf16Ex failed: %Rrc\n", rc));
-    return NULL;
-}
-
-
-/**
- * @returns Updated pbDst on success, NULL on failure.
- */
-static uint8_t *vboxSfOs2CopyUtf8NameAndUpperCase(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
-{
-    /* Convert UTF-8 to UTF-16: */
-    int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
-    if (RT_SUCCESS(rc))
-    {
-        char *pszDst = (char *)(pbDst + 1);
-        rc = KernStrFromUcs(NULL, pszDst, RTUtf16ToUpper(pwszTmp), CCHMAXPATHCOMP, cwcTmp);
-        if (rc == NO_ERROR)
-        {
-            size_t cchDst = strlen(pszDst);
-            *pbDst++ = (uint8_t)cchDst;
-            pbDst   += cchDst;
-            *pbDst++ = '\0';
-            return pbDst;
-        }
-        LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: KernStrFromUcs failed: %d\n", rc));
-    }
-    else
-        LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: RTStrToUtf16Ex failed: %Rrc\n", rc));
+static uint8_t *vboxSfOs2CopyUtf16Name(uint8_t *pbDst, PRTUTF16 pwszSrc, size_t cwcSrc)
+{
+    char *pszDst = (char *)pbDst + 1;
+    APIRET rc = KernStrFromUcs(NULL, pszDst, pwszSrc, CCHMAXPATHCOMP, cwcSrc);
+    if (rc == NO_ERROR)
+    {
+        size_t cchDst = strlen(pszDst);
+        *pbDst++ = (uint8_t)cchDst;
+        pbDst   += cchDst;
+        *pbDst++ = '\0';
+        return pbDst;
+    }
+    LogRel(("vboxSfOs2CopyUtf8Name: KernStrFromUcs failed: %d\n", rc));
     return NULL;
 }
@@ -314,6 +270,6 @@
             && (   pDataBuf->fLongFilenames
                 || pEntry->cucShortName
-                || vboxSfOs2IsUtf8Name8dot3((char *)pEntry->name.String.utf8, pEntry->name.u16Length,
-                                            pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp))))
+                || vboxSfOs2IsUtf16Name8dot3(pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16),
+                                             (char *)pDataBuf->abStaging, sizeof(pDataBuf->abStaging))))
         {
             /*
@@ -402,9 +358,7 @@
             /* The length prefixed filename. */
             if (pDataBuf->fLongFilenames)
-                pbDst = vboxSfOs2CopyUtf8Name(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
-                                           (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
+                pbDst = vboxSfOs2CopyUtf16Name(pbDst, pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16));
             else if (pEntry->cucShortName == 0)
-                pbDst = vboxSfOs2CopyUtf8NameAndUpperCase(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
-                                                       (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
+                pbDst = vboxSfOs2CopyUtf16NameAndUpperCase(pbDst, pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16));
             else
                 pbDst = vboxSfOs2CopyUtf16NameAndUpperCase(pbDst, pEntry->uszShortName, pEntry->cucShortName);
@@ -520,4 +474,5 @@
     if (rc == NO_ERROR)
     {
+LogRel(("pStrFolderPath: %#x %#x '%ls'\n", pStrFolderPath->u16Size, pStrFolderPath->u16Length, pStrFolderPath->String.ucs2));
         /*
          * Look for a wildcard filter at the end of the path, saving it all for
@@ -525,46 +480,46 @@
          */
         PSHFLSTRING pFilter = NULL;
-        char *pszFilter = RTPathFilename((char *)pStrFolderPath->String.utf8);
-        if (   pszFilter
-            && (   strchr(pszFilter, '*') != NULL
-                || strchr(pszFilter, '?') != NULL))
+        PRTUTF16 pwszFilter = RTPathFilenameUtf16(pStrFolderPath->String.utf16);
+        if (   pwszFilter
+            && (   RTUtf16Chr(pwszFilter, '*') != NULL
+                || RTUtf16Chr(pwszFilter, '?') != NULL))
         {
-            if (strcmp(pszFilter, "*.*") == 0)
+            if (RTUtf16CmpAscii(pwszFilter, "*.*") == 0)
             {
                 /* All files, no filtering needed. Just drop the filter expression from the directory path. */
-                *pszFilter = '\0';
-                pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
+                *pwszFilter = '\0';
+                pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]);
             }
             else
             {
                 /* Duplicate the whole path. */
-                pFilter = vboxSfOs2StrDup(pStrFolderPath->String.ach, pStrFolderPath->u16Length);
+                pFilter = vboxSfOs2StrDup(pStrFolderPath);
                 if (pFilter)
                 {
                     /* Drop filter from directory path. */
-                    *pszFilter = '\0';
-                    pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
+                    *pwszFilter = '\0';
+                    pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]);
 
                     /* Convert filter part of the copy to NT speak. */
-                    pszFilter = (char *)&pFilter->String.utf8[(uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]];
+                    pwszFilter = (PRTUTF16)&pFilter->String.utf8[(uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]];
                     for (;;)
                     {
-                        char ch = *pszFilter;
-                        if (ch == '?')
-                            *pszFilter = '>';       /* The DOS question mark: Matches one char, but dots and end-of-name eats them. */
-                        else if (ch == '.')
+                        RTUTF16 wc = *pwszFilter;
+                        if (wc == '?')
+                            *pwszFilter = '>';      /* The DOS question mark: Matches one char, but dots and end-of-name eats them. */
+                        else if (wc == '.')
                         {
-                            char ch2 = pszFilter[1];
-                            if (ch2 == '*' || ch2 == '?')
-                                *pszFilter = '"';   /* The DOS dot: Matches a dot or end-of-name. */
+                            RTUTF16 wc2 = pwszFilter[1];
+                            if (wc2 == '*' || wc2 == '?')
+                                *pwszFilter = '"';  /* The DOS dot: Matches a dot or end-of-name. */
                         }
-                        else if (ch == '*')
+                        else if (wc == '*')
                         {
-                            if (pszFilter[1] == '.')
-                                *pszFilter = '<';   /* The DOS star: Matches zero or more chars except the DOS dot.*/
+                            if (pwszFilter[1] == '.')
+                                *pwszFilter = '<';  /* The DOS star: Matches zero or more chars except the DOS dot.*/
                         }
-                        else if (ch == '\0')
+                        else if (wc == '\0')
                             break;
-                        pszFilter++;
+                        pwszFilter++;
                     }
                 }
@@ -581,18 +536,24 @@
          * but if we do we should accept it only for the root.
          */
-        else if (pszFilter)
+        else if (pwszFilter)
         {
             pFilter = pStrFolderPath;
-            pStrFolderPath = vboxSfOs2StrDup(pFilter->String.ach, pszFilter - pFilter->String.ach);
-            if (!pStrFolderPath)
+            pStrFolderPath = vboxSfOs2StrAlloc(pwszFilter - pFilter->String.utf16);
+            if (pStrFolderPath)
+            {
+                pStrFolderPath->u16Length = (uint16_t)((uintptr_t)pwszFilter - (uintptr_t)pFilter->String.utf16);
+                memcpy(pStrFolderPath->String.utf16, pFilter->String.utf16, pStrFolderPath->u16Length);
+                pStrFolderPath->String.utf16[pStrFolderPath->u16Length / sizeof(RTUTF16)] = '\0';
+            }
+            else
                 rc = ERROR_NOT_ENOUGH_MEMORY;
         }
-        else if (!pszFilter && pStrFolderPath->u16Length > 1)
+        else if (!pwszFilter && pStrFolderPath->u16Length > 1)
         {
-            LogFlow(("FS32_FINDFIRST: Trailing slash (%s)\n", pStrFolderPath->String.utf8));
+            LogFlow(("FS32_FINDFIRST: Trailing slash (%ls)\n", pStrFolderPath->String.utf16));
             rc = ERROR_PATH_NOT_FOUND;
         }
         else
-            LogFlow(("FS32_FINDFIRST: Root dir (%s)\n", pStrFolderPath->String.utf8));
+            LogFlow(("FS32_FINDFIRST: Root dir (%ls)\n", pStrFolderPath->String.utf16));
 
         /*
@@ -626,6 +587,6 @@
                                  | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
             int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
-            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate(%s) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
-                     pStrFolderPath->String.ach, vrc, pParams->Result, pParams->Info.Attr.fMode, pParams->Handle));
+            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate(%ls) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
+                     pStrFolderPath->String.utf16, vrc, pParams->Result, pParams->Info.Attr.fMode, pParams->Handle));
             if (RT_SUCCESS(vrc))
             {
@@ -681,5 +642,5 @@
                         else
                         {
-                            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate returns NIL handle for '%s'\n", pStrFolderPath->String.utf8));
+                            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate returns NIL handle for '%ls'\n", pStrFolderPath->String.utf16));
                             rc = ERROR_PATH_NOT_FOUND;
                         }
Index: trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h
===================================================================
--- trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h	(revision 76105)
+++ trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h	(revision 76108)
@@ -47,4 +47,5 @@
 #include <iprt/list.h>
 #include <VBox/VBoxGuestLibSharedFolders.h>
+#include <VBox/VBoxGuest.h>
 
 
@@ -182,7 +183,4 @@
     /** Staging area for staging a full FILEFINDBUF4L (+ 32 safe bytes). */
     uint8_t             abStaging[RT_ALIGN_32(sizeof(FILEFINDBUF4L) + 32, 8)];
-    /** For temporary convertion to UTF-8 so we can use KernStrFromUcs to get
-     *  string encoded according to the process codepage. */
-    RTUTF16             wszTmp[260];
 } VBOXSFFSBUF;
 AssertCompileSizeAlignment(VBOXSFFSBUF, 8);
@@ -224,10 +222,12 @@
 extern VBGLSFCLIENT g_SfClient;
 
-PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength);
-PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc);
+PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength);
+PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc);
 void        vboxSfOs2StrFree(PSHFLSTRING pStr);
 
 APIRET      vboxSfOs2ResolvePath(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd,
                                  PVBOXSFFOLDER *ppFolder, PSHFLSTRING *ppStrFolderPath);
+APIRET      vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf,
+                                   PVBOXSFFOLDER *ppFolder, void **ppvBuf);
 void        vboxSfOs2ReleasePathAndFolder(PSHFLSTRING pStrPath, PVBOXSFFOLDER pFolder);
 void        vboxSfOs2ReleaseFolder(PVBOXSFFOLDER pFolder);
@@ -244,4 +244,46 @@
 DECLASM(PVBOXSFVP) Fsh32GetVolParams(USHORT hVbp, PVPFSI *ppVpFsi /*optional*/);
 
+
+
+/** Request structure for vboxSfOs2HostReqCreate.  */
+typedef struct VBOXSFCREATEREQ
+{
+    VBGLIOCIDCHGCMFASTCALL  Hdr;
+    VMMDevHGCMCall          Call;
+    VBoxSFParmCreate        Parms;
+    SHFLCREATEPARMS         CreateParms;
+    SHFLSTRING              StrPath;
+} VBOXSFCREATEREQ;
+
+/**
+ * SHFL_FN_CREATE request.
+ */
+DECLINLINE(int) vboxSfOs2HostReqCreate(PVBOXSFFOLDER pFolder, VBOXSFCREATEREQ *pReq)
+{
+    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+                                SHFL_FN_CREATE, SHFL_CPARMS_CREATE,
+                                RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + pReq->StrPath.u16Size);
+
+    pReq->Parms.id32Root.type                   = VMMDevHGCMParmType_32bit;
+    pReq->Parms.id32Root.u.value32              = pFolder->hHostFolder.root;
+
+    pReq->Parms.pStrPath.type                   = VMMDevHGCMParmType_Embedded;
+    pReq->Parms.pStrPath.u.Embedded.cbData      = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+    pReq->Parms.pStrPath.u.Embedded.offData     = RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->Parms.pStrPath.u.Embedded.fFlags      = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+
+    pReq->Parms.pCreateParms.type               = VMMDevHGCMParmType_Embedded;
+    pReq->Parms.pCreateParms.u.Embedded.cbData  = sizeof(pReq->CreateParms);
+    pReq->Parms.pCreateParms.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATEREQ, CreateParms) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+    pReq->Parms.pCreateParms.u.Embedded.fFlags  = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+
+    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr,
+                                 RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + pReq->StrPath.u16Size);
+    if (RT_SUCCESS(vrc))
+        vrc = pReq->Call.header.result;
+    return vrc;
+}
+
+
 #endif
 
