VirtualBox

Changeset 76108 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Dec 10, 2018 12:01:34 PM (6 years ago)
Author:
vboxsync
Message:

os2/VBoxSF: Use UTF-16 for talking to the host, fits better with conversions APIs in kernel. Experimenting with using single request buffers for open/create.

Location:
trunk/src/VBox/Additions/os2/VBoxSF
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSF.cpp

    r75558 r76108  
    189189
    190190/**
    191  * Allocates a SHFLSTRING buffer.
     191 * Allocates a SHFLSTRING buffer (UTF-16).
    192192 *
    193193 * @returns Pointer to a SHFLSTRING buffer, NULL if out of memory.
    194  * @param   cchLength   The desired string buffer length (excluding terminator).
    195  */
    196 PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength)
    197 {
    198     AssertReturn(cchLength <= 0x1000, NULL);
    199 
    200     PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchLength + 1);
     194 * @param   cwcLength   The desired string buffer length in UTF-16 units
     195 *                      (excluding terminator).
     196 */
     197PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength)
     198{
     199    AssertReturn(cwcLength <= 0x1000, NULL);
     200    uint16_t cb = (uint16_t)cwcLength + 1;
     201    cb *= sizeof(RTUTF16);
     202
     203    PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cb);
    201204    if (pStr)
    202205    {
    203         pStr->u16Size       = (uint16_t)(cchLength + 1);
    204         pStr->u16Length     = 0;
    205         pStr->String.ach[0] = '\0';
     206        pStr->u16Size         = cb;
     207        pStr->u16Length       = 0;
     208        pStr->String.utf16[0] = '\0';
    206209        return pStr;
    207210    }
     
    211214
    212215/**
    213  * Duplicates a UTF-8 string into a SHFLSTRING buffer.
     216 * Duplicates a shared folders string buffer (UTF-16).
    214217 *
    215218 * @returns Pointer to a SHFLSTRING buffer containing the copy.
    216219 *          NULL if out of memory or the string is too long.
    217  * @param   pachSrc     The string to clone.
    218  * @param   cchSrc      The length of the substring, RTMAX_STR for the whole.
    219  */
    220 PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc)
    221 {
    222     if (cchSrc == RTSTR_MAX)
    223         cchSrc = strlen(pachSrc);
    224     if (cchSrc < 0x1000)
    225     {
    226         PSHFLSTRING pStr = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + cchSrc + 1);
    227         if (pStr)
    228         {
    229             pStr->u16Size  = (uint16_t)(cchSrc + 1);
    230             pStr->u16Length = (uint16_t)cchSrc;
    231             memcpy(pStr->String.ach, pachSrc, cchSrc);
    232             pStr->String.ach[cchSrc] = '\0';
    233             return pStr;
    234         }
     220 * @param   pSrc        The string to clone.
     221 */
     222PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc)
     223{
     224    PSHFLSTRING pDst = (PSHFLSTRING)VbglR0PhysHeapAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Length + sizeof(RTUTF16));
     225    if (pDst)
     226    {
     227        pDst->u16Size   = pSrc->u16Length + (uint16_t)sizeof(RTUTF16);
     228        pDst->u16Length = pSrc->u16Length;
     229        memcpy(&pDst->String, &pSrc->String, pSrc->u16Length);
     230        pDst->String.utf16[pSrc->u16Length / sizeof(RTUTF16)] = '\0';
     231        return pDst;
    235232    }
    236233    return NULL;
     
    268265    int rc = VbglR0SfConnect(&g_SfClient);
    269266    if (RT_SUCCESS(rc))
    270     {
    271         rc = VbglR0SfSetUtf8(&g_SfClient);
    272         if (RT_SUCCESS(rc))
    273             g_fIsConnectedToService = true;
    274         else
    275         {
    276             LogRel(("VbglR0SfSetUtf8 failed: %Rrc\n", rc));
    277             VbglR0SfDisconnect(&g_SfClient);
    278         }
    279     }
     267        g_fIsConnectedToService = true;
    280268    else
    281269        LogRel(("VbglR0SfConnect failed: %Rrc\n", rc));
     
    358346 *
    359347 * @returns VBox status code.
    360  * @param   pName       The name of the folder to map.
     348 * @param   pName       The name of the folder to map - ASCII (not UTF-16!).
     349 *                      Must be large enough to hold UTF-16 expansion of the
     350 *                      string, will do so upon return.
    361351 * @param   pszTag      Folder tag (for the VBoxService automounter).  Optional.
    362352 * @param   ppFolder    Where to return the folder structure on success.
     
    386376            memcpy(&pNew->szName[pName->u16Length + 1], pszTag, cbTag);
    387377
     378        /* Expand the folder name to UTF-16. */
     379        uint8_t                 off     = pNew->cchName;
     380        uint8_t volatile const *pbSrc   = &pName->String.utf8[0];
     381        RTUTF16 volatile       *pwcDst  = &pName->String.utf16[0];
     382        do
     383            pwcDst[off] = pbSrc[off];
     384        while (off-- > 0);
     385        pName->u16Length *= sizeof(RTUTF16);
     386        Assert(pName->u16Length + sizeof(RTUTF16) <= pName->u16Size);
     387
     388        /* Try do the mapping.*/
    388389        rc = VbglR0SfMapFolder(&g_SfClient, pName, &pNew->hHostFolder);
    389390        if (RT_SUCCESS(rc))
     
    397398        else
    398399        {
    399             LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%.*s,) -> %Rrc\n", pName->u16Length, pName->String.utf8, rc));
     400            LogRel(("vboxSfOs2MapFolder: VbglR0SfMapFolder(,%s,) -> %Rrc\n", pNew->szName, rc));
    400401            RTMemFree(pNew);
    401402        }
     
    465466
    466467/**
    467  * Converts a path to UTF-8 and puts it in a VBGL friendly buffer.
     468 * Converts a path to UTF-16 and puts it in a VBGL friendly buffer.
    468469 *
    469470 * @returns OS/2 status code
     
    474475APIRET vboxSfOs2ConvertPath(const char *pszFolderPath, PSHFLSTRING *ppStr)
    475476{
    476     /* Skip unnecessary leading slashes. */
     477    /*
     478     * Skip unnecessary leading slashes.
     479     */
    477480    char ch = *pszFolderPath;
    478481    if (ch == '\\' || ch == '/')
     
    480483            pszFolderPath++;
    481484
    482     /** @todo do proper codepage -> utf8 conversion and straighten out
    483      *        everything... */
     485    /*
     486     * Since the KEE unicode conversion routines does not seem to know of
     487     * surrogate pairs, we will get a very good output size estimate by
     488     * using strlen() on the input.
     489     */
    484490    size_t cchSrc = strlen(pszFolderPath);
    485     PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc);
     491    PSHFLSTRING pDst = vboxSfOs2StrAlloc(cchSrc + 4 /*fudge*/);
    486492    if (pDst)
    487493    {
    488         pDst->u16Length = (uint16_t)cchSrc;
    489         memcpy(pDst->String.utf8, pszFolderPath, cchSrc);
    490         pDst->String.utf8[cchSrc] = '\0';
    491         *ppStr = pDst;
    492         return NO_ERROR;
    493     }
     494        APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
     495        if (rc == NO_ERROR)
     496        {
     497            pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
     498            *ppStr = pDst;
     499            return NO_ERROR;
     500        }
     501        VbglR0PhysHeapFree(pDst);
     502
     503        /*
     504         * This shouldn't happen, but just in case we try again with
     505         * twice the buffer size.
     506         */
     507        if (rc == 0x20412 /*ULS_BUFFERFULL*/)
     508        {
     509            pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2);
     510            if (pDst)
     511            {
     512                rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
     513                if (rc == NO_ERROR)
     514                {
     515                    pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
     516                    *ppStr = pDst;
     517                    return NO_ERROR;
     518                }
     519                VbglR0PhysHeapFree(pDst);
     520                LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
     521            }
     522        }
     523        else
     524            LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
     525    }
     526
     527    LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x\n", cchSrc));
    494528    *ppStr = NULL;
     529    return ERROR_NOT_ENOUGH_MEMORY;
     530}
     531
     532
     533/**
     534 * Converts a path to UTF-16 and puts it in a VBGL friendly buffer within a
     535 * larger buffer.
     536 *
     537 * @returns OS/2 status code
     538 * @param   pszFolderPath   The path to convert.
     539 * @param   offStrInBuf     The offset of the SHLFSTRING in the return buffer.
     540 *                          This first part of the buffer is zeroed.
     541 * @param   ppvBuf          Where to return the pointer to the buffer.  Free
     542 *                          using vboxSfOs2FreePath.
     543 */
     544APIRET vboxSfOs2ConvertPathEx(const char *pszFolderPath, uint32_t offStrInBuf, void **ppvBuf)
     545{
     546    /*
     547     * Skip unnecessary leading slashes.
     548     */
     549    char ch = *pszFolderPath;
     550    if (ch == '\\' || ch == '/')
     551        while ((ch = pszFolderPath[1]) == '\\' || ch == '/')
     552            pszFolderPath++;
     553
     554    /*
     555     * Since the KEE unicode conversion routines does not seem to know of
     556     * surrogate pairs, we will get a very good output size estimate by
     557     * using strlen() on the input.
     558     */
     559    size_t cchSrc = strlen(pszFolderPath);
     560    void *pvBuf = VbglR0PhysHeapAlloc(offStrInBuf + SHFLSTRING_HEADER_SIZE + (cchSrc + 4) * sizeof(RTUTF16));
     561    if (pvBuf)
     562    {
     563        RT_BZERO(pvBuf, offStrInBuf);
     564
     565        PSHFLSTRING pDst = (PSHFLSTRING)((uint8_t *)pvBuf + offStrInBuf);
     566        APIRET rc = KernStrToUcs(NULL, &pDst->String.utf16[0], (char *)pszFolderPath, cchSrc + 4, cchSrc);
     567        if (rc == NO_ERROR)
     568        {
     569            pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
     570            pDst->u16Size   = (uint16_t)((cchSrc + 4) * sizeof(RTUTF16));
     571            Assert(pDst->u16Length < pDst->u16Size);
     572            *ppvBuf = pvBuf;
     573            return NO_ERROR;
     574        }
     575        VbglR0PhysHeapFree(pvBuf);
     576
     577#if 0
     578        /*
     579         * This shouldn't happen, but just in case we try again with
     580         * twice the buffer size.
     581         */
     582        if (rc == 0x20412 /*ULS_BUFFERFULL*/)
     583        {
     584            pDst = vboxSfOs2StrAlloc((cchSrc + 16) * 2);
     585            if (pDst)
     586            {
     587                rc = KernStrToUcs(NULL, pDst->String.utf16, (char *)pszFolderPath, (cchSrc + 16) * 2, cchSrc);
     588                if (rc == NO_ERROR)
     589                {
     590                    pDst->u16Length = (uint16_t)RTUtf16Len(pDst->String.utf16) * (uint16_t)sizeof(RTUTF16);
     591                    *ppStr = pDst;
     592                    return NO_ERROR;
     593                }
     594                VbglR0PhysHeapFree(pDst);
     595                LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
     596            }
     597        }
     598        else
     599#endif
     600            LogRel(("vboxSfOs2ConvertPath: KernStrToUcs returns %#x for %.*Rhxs\n", rc, cchSrc, pszFolderPath));
     601    }
     602
     603    LogRel(("vboxSfOs2ConvertPath: Out of memory - cchSrc=%#x offStrInBuf=%#x\n", cchSrc, offStrInBuf));
     604    *ppvBuf = NULL;
    495605    return ERROR_NOT_ENOUGH_MEMORY;
    496606}
     
    553663         * Copy the name into the buffer format that Vbgl desires.
    554664         */
    555         PSHFLSTRING pStrName = vboxSfOs2StrDup(pachFolderName, cchFolderName);
     665        PSHFLSTRING pStrName = vboxSfOs2StrAlloc(cchFolderName);
    556666        if (pStrName)
    557667        {
     668            memcpy(pStrName->String.ach, pachFolderName, cchFolderName);
     669            pStrName->String.ach[cchFolderName] = '\0';
     670            pStrName->u16Length = (uint16_t)cchFolderName;
     671
    558672            /*
    559673             * Do the attaching.
     
    692806                 */
    693807                rc = vboxSfOs2ConvertPath(&pszPath[3], ppStrFolderPath);
     808                if (rc == NO_ERROR)
     809                    return rc;
     810
     811                vboxSfOs2ReleaseFolder(pFolder);
     812                *ppFolder = NULL;
     813                return rc;
     814            }
     815            KernReleaseSharedMutex(&g_MtxFolders);
     816            LogRel(("vboxSfOs2ResolvePath: No folder mapped on '%s'. Detach race?\n", pszPath));
     817            return ERROR_PATH_NOT_FOUND;
     818        }
     819        LogRel(("vboxSfOs2ResolvePath: No root slash: '%s'\n", pszPath));
     820        return ERROR_PATH_NOT_FOUND;
     821    }
     822    LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
     823    RT_NOREF_PV(pCdFsd); RT_NOREF_PV(offCurDirEnd);
     824    return ERROR_PATH_NOT_FOUND;
     825}
     826
     827
     828/**
     829 * Resolves the given path to a folder structure and folder relative string,
     830 * the latter placed within a larger request buffer.
     831 *
     832 * @returns OS/2 status code.
     833 * @param   pszPath         The path to resolve.
     834 * @param   pCdFsd          The IFS dependent CWD structure if present.
     835 * @param   offCurDirEnd    The offset into @a pszPath of the CWD.  -1 if not
     836 *                          CWD relative path.
     837 * @param   offStrInBuf     The offset of the SHLFSTRING in the return buffer.
     838 *                          This first part of the buffer is zeroed.
     839 * @param   ppFolder        Where to return the referenced pointer to the folder
     840 *                          structure.  Call vboxSfOs2ReleaseFolder() when done.
     841 * @param   ppvBuf          Where to return the Pointer to the buffer.  Free
     842 *                          using VbglR0PhysHeapFree.
     843 */
     844APIRET vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf,
     845                              PVBOXSFFOLDER *ppFolder, void **ppvBuf)
     846{
     847    APIRET rc;
     848
     849    /*
     850     * UNC path?  Reject the prefix to be on the safe side.
     851     */
     852    char ch = pszPath[0];
     853    if (ch == '\\' || ch == '/')
     854    {
     855        size_t cchPrefix = vboxSfOs2UncPrefixLength(pszPath);
     856        if (cchPrefix > 0)
     857        {
     858            /* Find the length of the folder name (share). */
     859            const char *pszFolderName = &pszPath[cchPrefix];
     860            size_t      cchFolderName = 0;
     861            while ((ch = pszFolderName[cchFolderName]) != '\0' && ch != '\\' && ch != '/')
     862            {
     863                if ((uint8_t)ch >= 0x20 && (uint8_t)ch <= 0x7f && ch != ':')
     864                    cchFolderName++;
     865                else
     866                {
     867                    LogRel(("vboxSfOs2ResolvePath: Invalid share name (@%u): %.*Rhxs\n",
     868                            cchPrefix + cchFolderName, strlen(pszPath), pszPath));
     869                    return ERROR_INVALID_NAME;
     870                }
     871            }
     872            if (cchFolderName >= VBOXSFOS2_MAX_FOLDER_NAME)
     873            {
     874                LogRel(("vboxSfOs2ResolvePath: Folder name is too long: %u, max %u (%s)\n",
     875                        cchFolderName, VBOXSFOS2_MAX_FOLDER_NAME, pszPath));
     876                return ERROR_FILENAME_EXCED_RANGE;
     877            }
     878
     879            /*
     880             * Look for the share.
     881             */
     882            KernRequestSharedMutex(&g_MtxFolders);
     883            PVBOXSFFOLDER pFolder = *ppFolder = vboxSfOs2FindAndRetainFolder(pszFolderName, cchFolderName);
     884            if (pFolder)
     885            {
     886                vboxSfOs2RetainFolder(pFolder);
     887                KernReleaseSharedMutex(&g_MtxFolders);
     888            }
     889            else
     890            {
     891                uint32_t const uRevBefore = g_uFolderRevision;
     892                KernReleaseSharedMutex(&g_MtxFolders);
     893                rc = vboxSfOs2AttachUncAndRetain(pszFolderName, cchFolderName, uRevBefore, ppFolder);
     894                if (rc == NO_ERROR)
     895                    pFolder = *ppFolder;
     896                else
     897                    return rc;
     898            }
     899
     900            /*
     901             * Convert the path and put it in a Vbgl compatible buffer..
     902             */
     903            rc = vboxSfOs2ConvertPathEx(&pszFolderName[cchFolderName], offStrInBuf, ppvBuf);
     904            if (rc == NO_ERROR)
     905                return rc;
     906
     907            vboxSfOs2ReleaseFolder(pFolder);
     908            *ppFolder = NULL;
     909            return rc;
     910        }
     911
     912        LogRel(("vboxSfOs2ResolvePath: Unexpected path: %s\n", pszPath));
     913        return ERROR_PATH_NOT_FOUND;
     914    }
     915
     916    /*
     917     * Drive letter?
     918     */
     919    ch &= ~0x20; /* upper case */
     920    if (   ch >= 'A'
     921        && ch <= 'Z'
     922        && pszPath[1] == ':')
     923    {
     924        unsigned iDrive = ch - 'A';
     925        ch  = pszPath[2];
     926        if (ch == '\\' || ch == '/')
     927        {
     928            KernRequestSharedMutex(&g_MtxFolders);
     929            PVBOXSFFOLDER pFolder = *ppFolder = g_apDriveFolders[iDrive];
     930            if (pFolder)
     931            {
     932                vboxSfOs2RetainFolder(pFolder);
     933                KernReleaseSharedMutex(&g_MtxFolders);
     934
     935                /*
     936                 * Convert the path and put it in a Vbgl compatible buffer..
     937                 */
     938                rc = vboxSfOs2ConvertPathEx(&pszPath[3], offStrInBuf, ppvBuf);
    694939                if (rc == NO_ERROR)
    695940                    return rc;
     
    10061251    RT_NOREF(uType); /* pass 1 or pass 2 doesn't matter to us, we've only got one 'server'. */
    10071252
    1008     if (vboxSfOs2UncPrefixLength(pszName) > 0 )
     1253    if (vboxSfOs2UncPrefixLength(pszName) > 0)
    10091254        return NO_ERROR;
    10101255    return ERROR_NOT_SUPPORTED;
     
    10741319                {
    10751320                    SHFLSTRING Path;
    1076                     uint8_t    abPadding[SHFLSTRING_HEADER_SIZE + 4];
     1321                    uint8_t    abPadding[SHFLSTRING_HEADER_SIZE + 4 * sizeof(RTUTF16)];
    10771322                };
    10781323            } Open;
     
    10961341        pu->Open.Params.CreateFlags = SHFL_CF_DIRECTORY   | SHFL_CF_ACT_FAIL_IF_NEW  | SHFL_CF_ACT_OPEN_IF_EXISTS
    10971342                                    | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
    1098         pu->Open.Path.u16Size   = 3;
    1099         pu->Open.Path.u16Length = 2;
    1100         pu->Open.Path.String.utf8[0] = '\\';
    1101         pu->Open.Path.String.utf8[1] = '.';
    1102         pu->Open.Path.String.utf8[2] = '\0';
     1343        pu->Open.Path.u16Size   = 3 * sizeof(RTUTF16);
     1344        pu->Open.Path.u16Length = 2 * sizeof(RTUTF16);
     1345        pu->Open.Path.String.utf16[0] = '\\';
     1346        pu->Open.Path.String.utf16[1] = '.';
     1347        pu->Open.Path.String.utf16[2] = '\0';
    11031348
    11041349        int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, &pu->Open.Path, &pu->Open.Params);
     
    12721517{
    12731518    LogFlow(("FS32_MKDIR: pCdFsi=%p pCdFsd=%p pszDir=%p:{%s} pEAOp=%p fFlags=%#x\n", pCdFsi, pCdFsd, pszDir, pszDir, offCurDirEnd, pEaOp, fFlags));
     1519    RT_NOREF(fFlags);
    12741520
    12751521    /*
     
    16261872    LogFlow(("FS32_FILEATTRIBUTE: fFlags=%#x pCdFsi=%p:{%#x,%s} pCdFsd=%p pszName=%p:{%s} offCurDirEnd=%d pfAttr=%p\n",
    16271873             fFlags, pCdFsi, pCdFsi->cdi_hVPB, pCdFsi->cdi_curdir, pCdFsd, pszName, pszName, offCurDirEnd, pfAttr));
    1628     RT_NOREF(offCurDirEnd);
     1874    RT_NOREF(pCdFsi, offCurDirEnd);
    16291875
    16301876    APIRET rc;
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFile.cpp

    r75650 r76108  
    5050    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",
    5151             pCdFsi, pCdFsd, pszName, pszName, offCurDirEnd, pSfFsi, pSfFsd, fOpenMode, fOpenFlags, puAction, fAttribs, pbEaBuf, pfGenFlag));
    52     RT_NOREF(pfGenFlag);
     52    RT_NOREF(pfGenFlag, pCdFsi);
    5353
    5454    /*
     
    7373    }
    7474
    75     SHFLCREATEPARMS *pParams = (SHFLCREATEPARMS *)VbglR0PhysHeapAlloc(sizeof(*pParams));
    76     if (!pParams)
    77         return ERROR_NOT_ENOUGH_MEMORY;
    78     RT_ZERO(*pParams);
    79 
     75    /*
     76     * Allocate request buffer and resovle the path to folder and folder relative path.
     77     */
     78    PVBOXSFFOLDER       pFolder;
     79    VBOXSFCREATEREQ    *pReq;
     80    APIRET rc = vboxSfOs2ResolvePathEx(pszName, pCdFsd, offCurDirEnd, RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath),
     81                                       &pFolder, (void **)&pReq);
     82    LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
     83    if (rc == NO_ERROR)
     84    { /* likely */ }
     85    else
     86        return rc;
     87
     88    /*
     89     * Continue validating and converting parameters.
     90     */
    8091    /* access: */
    8192    if (fOpenMode & OPEN_ACCESS_READWRITE)
    82         pParams->CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
     93        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READWRITE | SHFL_CF_ACCESS_ATTR_READWRITE;
    8394    else if (fOpenMode & OPEN_ACCESS_WRITEONLY)
    84         pParams->CreateFlags = SHFL_CF_ACCESS_WRITE     | SHFL_CF_ACCESS_ATTR_WRITE;
     95        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_WRITE     | SHFL_CF_ACCESS_ATTR_WRITE;
    8596    else
    86         pParams->CreateFlags = SHFL_CF_ACCESS_READ      | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
     97        pReq->CreateParms.CreateFlags = SHFL_CF_ACCESS_READ      | SHFL_CF_ACCESS_ATTR_READ; /* read or/and exec */
    8798
    8899    /* Sharing: */
    89100    switch (fOpenMode & (OPEN_SHARE_DENYNONE | OPEN_SHARE_DENYREADWRITE | OPEN_SHARE_DENYREAD | OPEN_SHARE_DENYWRITE))
    90101    {
    91         case OPEN_SHARE_DENYNONE:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
    92         case OPEN_SHARE_DENYWRITE:      pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
    93         case OPEN_SHARE_DENYREAD:       pParams->CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
    94         case OPEN_SHARE_DENYREADWRITE:  pParams->CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
    95         case 0:                         pParams->CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
     102        case OPEN_SHARE_DENYNONE:       pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYNONE; break;
     103        case OPEN_SHARE_DENYWRITE:      pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break;
     104        case OPEN_SHARE_DENYREAD:       pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYREAD; break;
     105        case OPEN_SHARE_DENYREADWRITE:  pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYALL; break;
     106        case 0:                         pReq->CreateParms.CreateFlags |= SHFL_CF_ACCESS_DENYWRITE; break; /* compatibility */
    96107        default:
    97108            LogRel(("FS32_OPENCREATE: Invalid file sharing mode: %#x\n", fOpenMode));
    98             VbglR0PhysHeapFree(pParams);
     109            VbglR0PhysHeapFree(pReq);
    99110            return VERR_INVALID_PARAMETER;
    100111
     
    104115    switch (fOpenFlags & 0x13)
    105116    {
    106         case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x00 */
    107             pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     117        case                                 OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x00 */
     118            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
    108119            break;
    109         case                        OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x10 */
    110             pParams->CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     120        case                                 OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x10 */
     121            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
    111122            break;
    112         case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x01 */
    113             pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     123        case                                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:      /* 0x01 */
     124            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
    114125            break;
    115         case                        OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x11 */
    116             pParams->CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     126        case                                 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW:    /* 0x11 */
     127            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
    117128            break;
    118         case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:   /* 0x02 */
    119             pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
     129        case                                 OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW:   /* 0x02 */
     130            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_FAIL_IF_NEW;
    120131            break;
    121         case                        OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
    122             pParams->CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
     132        case                                 OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW: /* 0x12 */
     133            pReq->CreateParms.CreateFlags |= SHFL_CF_ACT_REPLACE_IF_EXISTS | SHFL_CF_ACT_CREATE_IF_NEW;
    123134            break;
    124135        default:
    125136            LogRel(("FS32_OPENCREATE: Invalid file open flags: %#x\n", fOpenFlags));
    126             VbglR0PhysHeapFree(pParams);
     137            VbglR0PhysHeapFree(pReq);
    127138            return VERR_INVALID_PARAMETER;
    128139    }
     
    131142
    132143    /* Attributes: */
    133     pParams->Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
     144    pReq->CreateParms.Info.Attr.fMode = ((uint32_t)fAttribs << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_OS2;
    134145
    135146    /* Initial size: */
    136147    if (pSfFsi->sfi_sizel > 0)
    137         pParams->Info.cbObject = pSfFsi->sfi_sizel;
    138 
    139     /*
    140      * Resolve path to a folder and folder relative path.
    141      */
    142     PVBOXSFFOLDER pFolder;
    143     PSHFLSTRING   pStrFolderPath;
    144     RT_NOREF(pCdFsi);
    145     APIRET rc = vboxSfOs2ResolvePath(pszName, pCdFsd, offCurDirEnd, &pFolder, &pStrFolderPath);
    146     LogFlow(("FS32_OPENCREATE: vboxSfOs2ResolvePath: -> %u pFolder=%p\n", rc, pFolder));
    147     if (rc == NO_ERROR)
    148     {
    149         /*
    150          * Try open the file.
    151          */
    152         int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
    153         LogFlow(("FS32_OPENCREATE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pParams->Result, pParams->Info.Attr.fMode));
    154         if (RT_SUCCESS(vrc))
     148        pReq->CreateParms.Info.cbObject = pSfFsi->sfi_sizel;
     149
     150    /*
     151     * Try open the file.
     152     */
     153    int vrc = vboxSfOs2HostReqCreate(pFolder, pReq);
     154    LogFlow(("FS32_OPENCREATE: VbglR0SfCreate -> %Rrc Result=%d fMode=%#x\n", vrc, pReq->CreateParms.Result, pReq->CreateParms.Info.Attr.fMode));
     155    if (RT_SUCCESS(vrc))
     156    {
     157        switch (pReq->CreateParms.Result)
    155158        {
    156             switch (pParams->Result)
    157             {
    158                 case SHFL_FILE_EXISTS:
    159                     if (pParams->Handle == SHFL_HANDLE_NIL)
    160                     {
    161                         rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
    162                         break;
    163                     }
    164                     RT_FALL_THRU();
    165                 case SHFL_FILE_CREATED:
    166                 case SHFL_FILE_REPLACED:
    167                     if (   pParams->Info.cbObject < _2G
    168                         || (fOpenMode & OPEN_FLAGS_LARGEFILE))
    169                     {
    170                         pSfFsd->u32Magic    = VBOXSFSYFI_MAGIC;
    171                         pSfFsd->pSelf       = pSfFsd;
    172                         pSfFsd->hHostFile   = pParams->Handle;
    173                         pSfFsd->pFolder     = pFolder;
    174 
    175                         uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
    176                         Assert(cOpenFiles < _32K);
    177                         pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
    178 
    179                         pSfFsi->sfi_sizel   = pParams->Info.cbObject;
    180                         pSfFsi->sfi_type    = STYPE_FILE;
    181                         pSfFsi->sfi_DOSattr = (uint8_t)((pParams->Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
    182                         int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
    183                         vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pParams->Info.BirthTime,        cMinLocalTimeDelta);
    184                         vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pParams->Info.AccessTime,       cMinLocalTimeDelta);
    185                         vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pParams->Info.ModificationTime, cMinLocalTimeDelta);
    186                         if (pParams->Result == SHFL_FILE_CREATED)
    187                             pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
    188 
    189                         *puAction = pParams->Result == SHFL_FILE_CREATED ? FILE_CREATED
    190                                   : pParams->Result == SHFL_FILE_EXISTS  ? FILE_EXISTED
    191                                   :                                        FILE_TRUNCATED;
    192 
    193                         Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
    194                         rc = NO_ERROR;
    195                     }
    196                     else
    197                     {
    198                         LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pParams->Info.cbObject, pszName));
    199                         VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pParams->Handle);
    200                         rc = ERROR_ACCESS_DENIED;
    201                     }
     159            case SHFL_FILE_EXISTS:
     160                if (pReq->CreateParms.Handle == SHFL_HANDLE_NIL)
     161                {
     162                    rc = ERROR_OPEN_FAILED; //ERROR_FILE_EXISTS;
    202163                    break;
    203 
    204                 case SHFL_PATH_NOT_FOUND:
    205                     rc = ERROR_PATH_NOT_FOUND;
    206                     break;
    207 
    208                 default:
    209                 case SHFL_FILE_NOT_FOUND:
    210                     rc = ERROR_OPEN_FAILED;
    211                     break;
    212             }
     164                }
     165                RT_FALL_THRU();
     166            case SHFL_FILE_CREATED:
     167            case SHFL_FILE_REPLACED:
     168                if (   pReq->CreateParms.Info.cbObject < _2G
     169                    || (fOpenMode & OPEN_FLAGS_LARGEFILE))
     170                {
     171                    pSfFsd->u32Magic    = VBOXSFSYFI_MAGIC;
     172                    pSfFsd->pSelf       = pSfFsd;
     173                    pSfFsd->hHostFile   = pReq->CreateParms.Handle;
     174                    pSfFsd->pFolder     = pFolder;
     175
     176                    uint32_t cOpenFiles = ASMAtomicIncU32(&pFolder->cOpenFiles);
     177                    Assert(cOpenFiles < _32K);
     178                    pFolder = NULL; /* Reference now taken by pSfFsd->pFolder. */
     179
     180                    pSfFsi->sfi_sizel   = pReq->CreateParms.Info.cbObject;
     181                    pSfFsi->sfi_type    = STYPE_FILE;
     182                    pSfFsi->sfi_DOSattr = (uint8_t)((pReq->CreateParms.Info.Attr.fMode & RTFS_DOS_MASK_OS2) >> RTFS_DOS_SHIFT);
     183                    int16_t cMinLocalTimeDelta = vboxSfOs2GetLocalTimeDelta();
     184                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_cdate, &pSfFsi->sfi_ctime, pReq->CreateParms.Info.BirthTime,        cMinLocalTimeDelta);
     185                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_adate, &pSfFsi->sfi_atime, pReq->CreateParms.Info.AccessTime,       cMinLocalTimeDelta);
     186                    vboxSfOs2DateTimeFromTimeSpec(&pSfFsi->sfi_mdate, &pSfFsi->sfi_mtime, pReq->CreateParms.Info.ModificationTime, cMinLocalTimeDelta);
     187                    if (pReq->CreateParms.Result == SHFL_FILE_CREATED)
     188                        pSfFsi->sfi_tstamp |= ST_PCREAT | ST_SCREAT | ST_PWRITE | ST_SWRITE | ST_PREAD | ST_SREAD;
     189
     190                    *puAction = pReq->CreateParms.Result == SHFL_FILE_CREATED ? FILE_CREATED
     191                              : pReq->CreateParms.Result == SHFL_FILE_EXISTS  ? FILE_EXISTED
     192                              :                                                 FILE_TRUNCATED;
     193
     194                    Log(("FS32_OPENCREATE: hHandle=%#RX64 for '%s'\n", pSfFsd->hHostFile, pszName));
     195                    rc = NO_ERROR;
     196                }
     197                else
     198                {
     199                    LogRel(("FS32_OPENCREATE: cbObject=%#RX64 no OPEN_FLAGS_LARGEFILE (%s)\n", pReq->CreateParms.Info.cbObject, pszName));
     200                    VbglR0SfClose(&g_SfClient, &pFolder->hHostFolder, pReq->CreateParms.Handle);
     201                    rc = ERROR_ACCESS_DENIED;
     202                }
     203                break;
     204
     205            case SHFL_PATH_NOT_FOUND:
     206                rc = ERROR_PATH_NOT_FOUND;
     207                break;
     208
     209            default:
     210            case SHFL_FILE_NOT_FOUND:
     211                rc = ERROR_OPEN_FAILED;
     212                break;
    213213        }
    214         else if (vrc == VERR_ALREADY_EXISTS)
    215             rc = ERROR_ACCESS_DENIED;
    216         else if (vrc == VERR_FILE_NOT_FOUND)
    217             rc = ERROR_OPEN_FAILED;
    218         else
    219             rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
    220         vboxSfOs2ReleasePathAndFolder(pStrFolderPath, pFolder);
    221     }
    222     VbglR0PhysHeapFree(pParams);
     214    }
     215    else if (vrc == VERR_ALREADY_EXISTS)
     216        rc = ERROR_ACCESS_DENIED;
     217    else if (vrc == VERR_FILE_NOT_FOUND)
     218        rc = ERROR_OPEN_FAILED;
     219    else
     220        rc = vboxSfOs2ConvertStatusToOs2(vrc, ERROR_PATH_NOT_FOUND);
     221    VbglR0PhysHeapFree(pReq);
     222    vboxSfOs2ReleaseFolder(pFolder);
    223223    LogFlow(("FS32_OPENCREATE: returns %u\n", rc));
    224224    return rc;
     
    465465    return rc;
    466466}
    467 
    468 #include <VBox/VBoxGuest.h>
    469 
    470467
    471468
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFFind.cpp

    r75461 r76108  
    4949 *
    5050 * @returns true if compatible, false if not.
    51  * @param   pszName     The name to inspect (UTF-8).
    52  * @param   cchName     The length of the name.
    53  * @param   pwszTmp     Buffer for test conversions.
    54  * @param   cwcTmp      The size of the buffer.
     51 * @param   pwszName    The name to inspect (UTF-16).
     52 * @param   cwcName     The length of the name.
     53 * @param   pszTmp      Buffer for test conversions.
     54 * @param   cbTmp       The size of the buffer.
    5555 */
    56 static bool vboxSfOs2IsUtf8Name8dot3(const char *pszName, size_t cchName, PRTUTF16 pwszTmp, size_t cwcTmp)
    57 {
    58     /* Reject names that must be too long when using maximum UTF-8 encoding. */
    59     if (cchName > (8 + 1 + 3) * 4)
     56static bool vboxSfOs2IsUtf16Name8dot3(PRTUTF16 pwszName, size_t cwcName, char *pszTmp, size_t cbTmp)
     57{
     58    /* Reject names that must be too long. */
     59    if (cwcName > 8 + 1 + 3)
    6060        return false;
    6161
    62     /* First char cannot be a dot. */
    63     if (*pszName == '.' || !*pszName)
     62    /* First char cannot be a dot, nor can it be an empty string. */
     63    if (*pwszName == '.' || !*pwszName)
    6464        return false;
    6565
     
    6767     * To basic checks on code point level before doing full conversion.
    6868     */
    69     const char *pszCursor = pszName;
    70     for (uint32_t cuc = 0; ; cuc++)
    71     {
    72         RTUNICP uCp;
    73         RTStrGetCpEx(&pszCursor, &uCp);
    74         if (uCp == '.')
     69    for (unsigned off = 0; ; off++)
     70    {
     71        RTUTF16 wc = pwszName[off];
     72        if (wc == '.')
    7573        {
    76             for (cuc = 0; ; cuc++)
    77             {
    78                 RTStrGetCpEx(&pszCursor, &uCp);
    79                 if (!uCp)
     74            unsigned const offMax = off + 3;
     75            for (++off;; off++)
     76            {
     77                wc = pwszName[off];
     78                if (!wc)
    8079                    break;
    81                 if (uCp == '.')
     80                if (wc == '.')
    8281                    return false;
    83                 if (cuc >= 3)
     82                if (off >= offMax)
    8483                    return false;
    8584            }
    8685            break;
    8786        }
    88         if (!uCp)
     87        if (!wc)
    8988            break;
    90         if (cuc >= 8)
     89        if (off >= 8)
    9190            return false;
    9291    }
    9392
    9493    /*
    95      * Convert to UTF-16 and then to native codepage.
    96      */
    97     size_t cwcActual = cwcTmp;
    98     int rc = RTStrToUtf16Ex(pszName, cchName, &pwszTmp, cwcTmp, &cwcActual);
    99     if (RT_SUCCESS(rc))
    100     {
    101         char *pszTmp = (char *)&pwszTmp[cwcActual + 1];
    102         rc = KernStrFromUcs(NULL, pszTmp, pwszTmp, (cwcTmp - cwcActual - 1) * sizeof(RTUTF16), cwcActual);
    103         if (rc != NO_ERROR)
    104         {
    105             LogRel(("vboxSfOs2IsUtf8Name8dot3: KernStrFromUcs failed: %d\n", rc));
     94     * Conver to the native code page.
     95     */
     96    APIRET rc = KernStrFromUcs(NULL, pszTmp, pwszName, cbTmp, cwcName);
     97    if (rc != NO_ERROR)
     98    {
     99        LogRel(("vboxSfOs2IsUtf8Name8dot3: KernStrFromUcs failed: %d\n", rc));
     100        return false;
     101    }
     102
     103    /*
     104     * Redo the check.
     105     * Note! This could be bogus if a DBCS leadin sequence collides with '.'.
     106     */
     107    for (unsigned cch = 0; ; cch++)
     108    {
     109        char ch = *pszTmp++;
     110        if (ch == '.')
     111            break;
     112        if (ch == '\0')
     113            return true;
     114        if (cch >= 8)
    106115            return false;
    107         }
    108 
    109         /*
    110          * Redo the check.
    111          * Note! This could be bogus if a DBCS leadin sequence collides with '.'.
    112          */
    113         for (uint32_t cch = 0; ; cch++)
    114         {
    115             char ch = *pszTmp++;
    116             if (ch == '.')
    117                 break;
    118             if (ch == '\0')
    119                 return true;
    120             if (cch >= 8)
    121                 return false;
    122         }
    123         for (uint32_t cch = 0; ; cch++)
    124         {
    125             char ch = *pszTmp++;
    126             if (ch == '\0')
    127                 return true;
    128             if (ch != '.')
    129                 return false;
    130             if (cch >= 3)
    131                 return false;
    132         }
    133     }
    134     else
    135         LogRel(("vboxSfOs2IsUtf8Name8dot3: RTStrToUtf16Ex failed: %Rrc\n", rc));
    136     return false;
     116    }
     117    for (unsigned cch = 0; ; cch++)
     118    {
     119        char ch = *pszTmp++;
     120        if (ch == '\0')
     121            return true;
     122        if (ch != '.')
     123            return false;
     124        if (cch >= 3)
     125            return false;
     126    }
    137127}
    138128
     
    141131 * @returns Updated pbDst on success, NULL on failure.
    142132 */
    143 static uint8_t *vboxSfOs2CopyUtf8Name(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
    144 {
    145     /* Convert UTF-8 to UTF-16: */
    146     int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
    147     if (RT_SUCCESS(rc))
    148     {
    149         char *pszDst = (char *)(pbDst + 1);
    150         rc = KernStrFromUcs(NULL, pszDst, pwszTmp, CCHMAXPATHCOMP, cwcTmp);
    151         if (rc == NO_ERROR)
    152         {
    153             size_t cchDst = strlen(pszDst);
    154             *pbDst++ = (uint8_t)cchDst;
    155             pbDst   += cchDst;
    156             *pbDst++ = '\0';
    157             return pbDst;
    158         }
    159         LogRel(("vboxSfOs2CopyUtf8Name: KernStrFromUcs failed: %d\n", rc));
    160     }
    161     else
    162         LogRel(("vboxSfOs2CopyUtf8Name: RTStrToUtf16Ex failed: %Rrc\n", rc));
    163     return NULL;
    164 }
    165 
    166 
    167 /**
    168  * @returns Updated pbDst on success, NULL on failure.
    169  */
    170 static uint8_t *vboxSfOs2CopyUtf8NameAndUpperCase(uint8_t *pbDst, PRTUTF16 pwszTmp, size_t cwcTmp, const char *pszSrc, size_t cchSrc)
    171 {
    172     /* Convert UTF-8 to UTF-16: */
    173     int rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszTmp, cwcTmp, &cwcTmp);
    174     if (RT_SUCCESS(rc))
    175     {
    176         char *pszDst = (char *)(pbDst + 1);
    177         rc = KernStrFromUcs(NULL, pszDst, RTUtf16ToUpper(pwszTmp), CCHMAXPATHCOMP, cwcTmp);
    178         if (rc == NO_ERROR)
    179         {
    180             size_t cchDst = strlen(pszDst);
    181             *pbDst++ = (uint8_t)cchDst;
    182             pbDst   += cchDst;
    183             *pbDst++ = '\0';
    184             return pbDst;
    185         }
    186         LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: KernStrFromUcs failed: %d\n", rc));
    187     }
    188     else
    189         LogRel(("vboxSfOs2CopyUtf8NameAndUpperCase: RTStrToUtf16Ex failed: %Rrc\n", rc));
     133static uint8_t *vboxSfOs2CopyUtf16Name(uint8_t *pbDst, PRTUTF16 pwszSrc, size_t cwcSrc)
     134{
     135    char *pszDst = (char *)pbDst + 1;
     136    APIRET rc = KernStrFromUcs(NULL, pszDst, pwszSrc, CCHMAXPATHCOMP, cwcSrc);
     137    if (rc == NO_ERROR)
     138    {
     139        size_t cchDst = strlen(pszDst);
     140        *pbDst++ = (uint8_t)cchDst;
     141        pbDst   += cchDst;
     142        *pbDst++ = '\0';
     143        return pbDst;
     144    }
     145    LogRel(("vboxSfOs2CopyUtf8Name: KernStrFromUcs failed: %d\n", rc));
    190146    return NULL;
    191147}
     
    314270            && (   pDataBuf->fLongFilenames
    315271                || pEntry->cucShortName
    316                 || vboxSfOs2IsUtf8Name8dot3((char *)pEntry->name.String.utf8, pEntry->name.u16Length,
    317                                             pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp))))
     272                || vboxSfOs2IsUtf16Name8dot3(pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16),
     273                                             (char *)pDataBuf->abStaging, sizeof(pDataBuf->abStaging))))
    318274        {
    319275            /*
     
    402358            /* The length prefixed filename. */
    403359            if (pDataBuf->fLongFilenames)
    404                 pbDst = vboxSfOs2CopyUtf8Name(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
    405                                            (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
     360                pbDst = vboxSfOs2CopyUtf16Name(pbDst, pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16));
    406361            else if (pEntry->cucShortName == 0)
    407                 pbDst = vboxSfOs2CopyUtf8NameAndUpperCase(pbDst, pDataBuf->wszTmp, sizeof(pDataBuf->wszTmp),
    408                                                        (char *)pEntry->name.String.utf8, pEntry->name.u16Length);
     362                pbDst = vboxSfOs2CopyUtf16NameAndUpperCase(pbDst, pEntry->name.String.utf16, pEntry->name.u16Length / sizeof(RTUTF16));
    409363            else
    410364                pbDst = vboxSfOs2CopyUtf16NameAndUpperCase(pbDst, pEntry->uszShortName, pEntry->cucShortName);
     
    520474    if (rc == NO_ERROR)
    521475    {
     476LogRel(("pStrFolderPath: %#x %#x '%ls'\n", pStrFolderPath->u16Size, pStrFolderPath->u16Length, pStrFolderPath->String.ucs2));
    522477        /*
    523478         * Look for a wildcard filter at the end of the path, saving it all for
     
    525480         */
    526481        PSHFLSTRING pFilter = NULL;
    527         char *pszFilter = RTPathFilename((char *)pStrFolderPath->String.utf8);
    528         if (   pszFilter
    529             && (   strchr(pszFilter, '*') != NULL
    530                 || strchr(pszFilter, '?') != NULL))
     482        PRTUTF16 pwszFilter = RTPathFilenameUtf16(pStrFolderPath->String.utf16);
     483        if (   pwszFilter
     484            && (   RTUtf16Chr(pwszFilter, '*') != NULL
     485                || RTUtf16Chr(pwszFilter, '?') != NULL))
    531486        {
    532             if (strcmp(pszFilter, "*.*") == 0)
     487            if (RTUtf16CmpAscii(pwszFilter, "*.*") == 0)
    533488            {
    534489                /* All files, no filtering needed. Just drop the filter expression from the directory path. */
    535                 *pszFilter = '\0';
    536                 pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
     490                *pwszFilter = '\0';
     491                pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]);
    537492            }
    538493            else
    539494            {
    540495                /* Duplicate the whole path. */
    541                 pFilter = vboxSfOs2StrDup(pStrFolderPath->String.ach, pStrFolderPath->u16Length);
     496                pFilter = vboxSfOs2StrDup(pStrFolderPath);
    542497                if (pFilter)
    543498                {
    544499                    /* Drop filter from directory path. */
    545                     *pszFilter = '\0';
    546                     pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]);
     500                    *pwszFilter = '\0';
     501                    pStrFolderPath->u16Length = (uint16_t)((uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]);
    547502
    548503                    /* Convert filter part of the copy to NT speak. */
    549                     pszFilter = (char *)&pFilter->String.utf8[(uint8_t *)pszFilter - &pStrFolderPath->String.utf8[0]];
     504                    pwszFilter = (PRTUTF16)&pFilter->String.utf8[(uint8_t *)pwszFilter - &pStrFolderPath->String.utf8[0]];
    550505                    for (;;)
    551506                    {
    552                         char ch = *pszFilter;
    553                         if (ch == '?')
    554                             *pszFilter = '>';       /* The DOS question mark: Matches one char, but dots and end-of-name eats them. */
    555                         else if (ch == '.')
     507                        RTUTF16 wc = *pwszFilter;
     508                        if (wc == '?')
     509                            *pwszFilter = '>';      /* The DOS question mark: Matches one char, but dots and end-of-name eats them. */
     510                        else if (wc == '.')
    556511                        {
    557                             char ch2 = pszFilter[1];
    558                             if (ch2 == '*' || ch2 == '?')
    559                                 *pszFilter = '"';   /* The DOS dot: Matches a dot or end-of-name. */
     512                            RTUTF16 wc2 = pwszFilter[1];
     513                            if (wc2 == '*' || wc2 == '?')
     514                                *pwszFilter = '"';  /* The DOS dot: Matches a dot or end-of-name. */
    560515                        }
    561                         else if (ch == '*')
     516                        else if (wc == '*')
    562517                        {
    563                             if (pszFilter[1] == '.')
    564                                 *pszFilter = '<';   /* The DOS star: Matches zero or more chars except the DOS dot.*/
     518                            if (pwszFilter[1] == '.')
     519                                *pwszFilter = '<';  /* The DOS star: Matches zero or more chars except the DOS dot.*/
    565520                        }
    566                         else if (ch == '\0')
     521                        else if (wc == '\0')
    567522                            break;
    568                         pszFilter++;
     523                        pwszFilter++;
    569524                    }
    570525                }
     
    581536         * but if we do we should accept it only for the root.
    582537         */
    583         else if (pszFilter)
     538        else if (pwszFilter)
    584539        {
    585540            pFilter = pStrFolderPath;
    586             pStrFolderPath = vboxSfOs2StrDup(pFilter->String.ach, pszFilter - pFilter->String.ach);
    587             if (!pStrFolderPath)
     541            pStrFolderPath = vboxSfOs2StrAlloc(pwszFilter - pFilter->String.utf16);
     542            if (pStrFolderPath)
     543            {
     544                pStrFolderPath->u16Length = (uint16_t)((uintptr_t)pwszFilter - (uintptr_t)pFilter->String.utf16);
     545                memcpy(pStrFolderPath->String.utf16, pFilter->String.utf16, pStrFolderPath->u16Length);
     546                pStrFolderPath->String.utf16[pStrFolderPath->u16Length / sizeof(RTUTF16)] = '\0';
     547            }
     548            else
    588549                rc = ERROR_NOT_ENOUGH_MEMORY;
    589550        }
    590         else if (!pszFilter && pStrFolderPath->u16Length > 1)
     551        else if (!pwszFilter && pStrFolderPath->u16Length > 1)
    591552        {
    592             LogFlow(("FS32_FINDFIRST: Trailing slash (%s)\n", pStrFolderPath->String.utf8));
     553            LogFlow(("FS32_FINDFIRST: Trailing slash (%ls)\n", pStrFolderPath->String.utf16));
    593554            rc = ERROR_PATH_NOT_FOUND;
    594555        }
    595556        else
    596             LogFlow(("FS32_FINDFIRST: Root dir (%s)\n", pStrFolderPath->String.utf8));
     557            LogFlow(("FS32_FINDFIRST: Root dir (%ls)\n", pStrFolderPath->String.utf16));
    597558
    598559        /*
     
    626587                                 | SHFL_CF_ACCESS_READ | SHFL_CF_ACCESS_ATTR_READ | SHFL_CF_ACCESS_DENYNONE;
    627588            int vrc = VbglR0SfCreate(&g_SfClient, &pFolder->hHostFolder, pStrFolderPath, pParams);
    628             LogFlow(("FS32_FINDFIRST: VbglR0SfCreate(%s) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
    629                      pStrFolderPath->String.ach, vrc, pParams->Result, pParams->Info.Attr.fMode, pParams->Handle));
     589            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate(%ls) -> %Rrc Result=%d fMode=%#x hHandle=%#RX64\n",
     590                     pStrFolderPath->String.utf16, vrc, pParams->Result, pParams->Info.Attr.fMode, pParams->Handle));
    630591            if (RT_SUCCESS(vrc))
    631592            {
     
    681642                        else
    682643                        {
    683                             LogFlow(("FS32_FINDFIRST: VbglR0SfCreate returns NIL handle for '%s'\n", pStrFolderPath->String.utf8));
     644                            LogFlow(("FS32_FINDFIRST: VbglR0SfCreate returns NIL handle for '%ls'\n", pStrFolderPath->String.utf16));
    684645                            rc = ERROR_PATH_NOT_FOUND;
    685646                        }
  • trunk/src/VBox/Additions/os2/VBoxSF/VBoxSFInternal.h

    r75405 r76108  
    4747#include <iprt/list.h>
    4848#include <VBox/VBoxGuestLibSharedFolders.h>
     49#include <VBox/VBoxGuest.h>
    4950
    5051
     
    182183    /** Staging area for staging a full FILEFINDBUF4L (+ 32 safe bytes). */
    183184    uint8_t             abStaging[RT_ALIGN_32(sizeof(FILEFINDBUF4L) + 32, 8)];
    184     /** For temporary convertion to UTF-8 so we can use KernStrFromUcs to get
    185      *  string encoded according to the process codepage. */
    186     RTUTF16             wszTmp[260];
    187185} VBOXSFFSBUF;
    188186AssertCompileSizeAlignment(VBOXSFFSBUF, 8);
     
    224222extern VBGLSFCLIENT g_SfClient;
    225223
    226 PSHFLSTRING vboxSfOs2StrAlloc(size_t cchLength);
    227 PSHFLSTRING vboxSfOs2StrDup(const char *pachSrc, size_t cchSrc);
     224PSHFLSTRING vboxSfOs2StrAlloc(size_t cwcLength);
     225PSHFLSTRING vboxSfOs2StrDup(PCSHFLSTRING pSrc);
    228226void        vboxSfOs2StrFree(PSHFLSTRING pStr);
    229227
    230228APIRET      vboxSfOs2ResolvePath(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd,
    231229                                 PVBOXSFFOLDER *ppFolder, PSHFLSTRING *ppStrFolderPath);
     230APIRET      vboxSfOs2ResolvePathEx(const char *pszPath, PVBOXSFCD pCdFsd, LONG offCurDirEnd, uint32_t offStrInBuf,
     231                                   PVBOXSFFOLDER *ppFolder, void **ppvBuf);
    232232void        vboxSfOs2ReleasePathAndFolder(PSHFLSTRING pStrPath, PVBOXSFFOLDER pFolder);
    233233void        vboxSfOs2ReleaseFolder(PVBOXSFFOLDER pFolder);
     
    244244DECLASM(PVBOXSFVP) Fsh32GetVolParams(USHORT hVbp, PVPFSI *ppVpFsi /*optional*/);
    245245
     246
     247
     248/** Request structure for vboxSfOs2HostReqCreate.  */
     249typedef struct VBOXSFCREATEREQ
     250{
     251    VBGLIOCIDCHGCMFASTCALL  Hdr;
     252    VMMDevHGCMCall          Call;
     253    VBoxSFParmCreate        Parms;
     254    SHFLCREATEPARMS         CreateParms;
     255    SHFLSTRING              StrPath;
     256} VBOXSFCREATEREQ;
     257
     258/**
     259 * SHFL_FN_CREATE request.
     260 */
     261DECLINLINE(int) vboxSfOs2HostReqCreate(PVBOXSFFOLDER pFolder, VBOXSFCREATEREQ *pReq)
     262{
     263    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     264                                SHFL_FN_CREATE, SHFL_CPARMS_CREATE,
     265                                RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + pReq->StrPath.u16Size);
     266
     267    pReq->Parms.id32Root.type                   = VMMDevHGCMParmType_32bit;
     268    pReq->Parms.id32Root.u.value32              = pFolder->hHostFolder.root;
     269
     270    pReq->Parms.pStrPath.type                   = VMMDevHGCMParmType_Embedded;
     271    pReq->Parms.pStrPath.u.Embedded.cbData      = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
     272    pReq->Parms.pStrPath.u.Embedded.offData     = RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     273    pReq->Parms.pStrPath.u.Embedded.fFlags      = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     274
     275    pReq->Parms.pCreateParms.type               = VMMDevHGCMParmType_Embedded;
     276    pReq->Parms.pCreateParms.u.Embedded.cbData  = sizeof(pReq->CreateParms);
     277    pReq->Parms.pCreateParms.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATEREQ, CreateParms) - sizeof(VBGLIOCIDCHGCMFASTCALL);
     278    pReq->Parms.pCreateParms.u.Embedded.fFlags  = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
     279
     280    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr,
     281                                 RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + pReq->StrPath.u16Size);
     282    if (RT_SUCCESS(vrc))
     283        vrc = pReq->Call.header.result;
     284    return vrc;
     285}
     286
     287
    246288#endif
    247289
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette