VirtualBox

Changeset 85408 in vbox


Ignore:
Timestamp:
Jul 22, 2020 8:49:55 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
139447
Message:

DnD/TransferList: More fixes + testcases.

Location:
trunk/src/VBox/GuestHost/DragAndDrop
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDTransferList.cpp

    r85382 r85408  
    5353
    5454/**
    55  * Initializes a transfer list.
     55 * Initializes a transfer list, internal version.
    5656 *
    5757 * @returns VBox status code.
     
    5959 * @param   pcszRootPathAbs     Absolute root path to use for this list. Optional and can be NULL.
    6060 */
    61 int DnDTransferListInit(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs)
     61static int dndTransferListInitInternal(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs)
    6262{
    6363    AssertPtrReturn(pList, VERR_INVALID_POINTER);
     
    8383
    8484    return VINF_SUCCESS;
     85}
     86
     87/**
     88 * Initializes a transfer list.
     89 *
     90 * @returns VBox status code.
     91 * @param   pList               Transfer list to initialize.
     92 * @param   pcszRootPathAbs     Absolute root path to use for this list. Optional and can be NULL.
     93 */
     94int DnDTransferListInit(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs)
     95{
     96    return dndTransferListInitInternal(pList, pcszRootPathAbs);
    8597}
    8698
     
    369381}
    370382
     383/**
     384 * Helper function for appending a local directory to a DnD transfer list.
     385 *
     386 * @returns VBox status code.
     387 * @param   pList               Transfer list to return total number of root entries for.
     388 * @param   pszPathAbs          Absolute path of directory to append.
     389 * @param   cbPathAbs           Size (in bytes) of absolute path of directory to append.
     390 * @param   fFlags              Transfer list flags to use for appending.
     391 */
     392static int dndTransferListAppenDirectory(PDNDTRANSFERLIST pList, char* pszPathAbs, size_t cbPathAbs,
     393                                         DNDTRANSFERLISTFLAGS fFlags)
     394{
     395    RTDIR hDir;
     396    int rc = RTDirOpen(&hDir, pszPathAbs);
     397    if (RT_FAILURE(rc))
     398        return rc;
     399
     400    const size_t cchPathAbs = RTStrNLen(pszPathAbs, cbPathAbs);
     401
     402    for (;;)
     403    {
     404        /* Get the next directory. */
     405        RTDIRENTRYEX dirEntry;
     406        rc = RTDirReadEx(hDir, &dirEntry, NULL, RTFSOBJATTRADD_UNIX,
     407                         RTPATH_F_ON_LINK /** @todo No symlinks yet. */);
     408        if (RT_SUCCESS(rc))
     409        {
     410            if (RTDirEntryExIsStdDotLink(&dirEntry))
     411                continue;
     412
     413            /* Check length. */
     414            if (dirEntry.cbName + cchPathAbs + 3 >= cbPathAbs)
     415            {
     416                rc = VERR_BUFFER_OVERFLOW;
     417                break;
     418            }
     419
     420            /* Append the directory entry to our absolute path. */
     421            memcpy(&pszPathAbs[cchPathAbs], dirEntry.szName, dirEntry.cbName + 1);
     422
     423            LogFlowFunc(("szName=%s, pszPathAbs=%s\n", dirEntry.szName, pszPathAbs));
     424
     425            switch (dirEntry.Info.Attr.fMode & RTFS_TYPE_MASK)
     426            {
     427                case RTFS_TYPE_DIRECTORY:
     428                {
     429                    rc = dndTransferListAppendPathNativeRecursive(pList, pszPathAbs, fFlags);
     430                    break;
     431                }
     432
     433                case RTFS_TYPE_FILE:
     434                {
     435                    rc = dndTransferListObjAdd(pList, pszPathAbs, dirEntry.Info.Attr.fMode, fFlags);
     436                    break;
     437                }
     438
     439                default:
     440                    /* Silently skip everything else. */
     441                    break;
     442            }
     443        }
     444        else if (rc == VERR_NO_MORE_FILES)
     445        {
     446            rc = VINF_SUCCESS;
     447            break;
     448        }
     449        else
     450            break;
     451    }
     452
     453    return rc;
     454}
     455
     456/**
     457 * Appends a native path to a DnD transfer list.
     458 *
     459 * @returns VBox status code.
     460 * @param   pList               Transfer list to append native path to.
     461 * @param   pcszPath            Path (native) to append.
     462 * @param   fFlags              Transfer list flags to use for appending.
     463 */
    371464static int dndTransferListAppendPathNative(PDNDTRANSFERLIST pList, const char *pcszPath, DNDTRANSFERLISTFLAGS fFlags)
    372465{
     
    394487        if (RTPathStartsWith(szPathAbs, pList->pszPathRootAbs))
    395488        {
    396             RTDIR hDir;
    397             rc = RTDirOpen(&hDir, szPathAbs);
     489            RTFSOBJINFO objInfo;
     490            rc = RTPathQueryInfo(szPathAbs, &objInfo, RTFSOBJATTRADD_NOTHING);
    398491            if (RT_SUCCESS(rc))
    399492            {
    400                 for (;;)
     493                switch (objInfo.Attr.fMode & RTFS_TYPE_MASK)
    401494                {
    402                     /* Get the next directory. */
    403                     RTDIRENTRYEX dirEntry;
    404                     rc = RTDirReadEx(hDir, &dirEntry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK /** @todo No symlinks yet. */);
    405                     if (RT_SUCCESS(rc))
    406                     {
    407                         if (RTDirEntryExIsStdDotLink(&dirEntry))
    408                             continue;
    409 
    410                         /* Check length. */
    411                         if (dirEntry.cbName + cchPathAbs + 3 >= sizeof(szPathAbs))
    412                         {
    413                             rc = VERR_BUFFER_OVERFLOW;
    414                             break;
    415                         }
    416 
    417                         /* Append the directory entry to our absolute path. */
    418                         memcpy(&szPathAbs[cchPathAbs], dirEntry.szName, dirEntry.cbName + 1);
    419 
    420                         LogFlowFunc(("szName=%s, szPathAbs=%s\n", dirEntry.szName, szPathAbs));
    421 
    422                         switch (dirEntry.Info.Attr.fMode & RTFS_TYPE_MASK)
    423                         {
    424                             case RTFS_TYPE_DIRECTORY:
    425                             {
    426                                 rc = dndTransferListAppendPathNativeRecursive(pList, szPathAbs, fFlags);
    427                                 break;
    428                             }
    429 
    430                             case RTFS_TYPE_FILE:
    431                             {
    432                                 rc = dndTransferListObjAdd(pList, szPathAbs, dirEntry.Info.Attr.fMode, fFlags);
    433                                 break;
    434                             }
    435 
    436                             default:
    437                                 rc = VERR_NOT_SUPPORTED;
    438                                 break;
    439                         }
    440 
    441                         if (RT_SUCCESS(rc))
    442                             rc = dndTransferListRootAdd(pList, dirEntry.szName);
    443                     }
    444                     else if (rc == VERR_NO_MORE_FILES)
    445                     {
    446                         rc = VINF_SUCCESS;
     495                    case RTFS_TYPE_DIRECTORY:
     496                        if (fFlags & DNDTRANSFERLIST_FLAGS_RECURSIVE)
     497                            rc = dndTransferListAppenDirectory(pList, szPathAbs, sizeof(szPathAbs), fFlags);
    447498                        break;
    448                     }
    449                     else
     499
     500                    case RTFS_TYPE_FILE:
     501                        rc = dndTransferListObjAdd(pList, szPathAbs, objInfo.Attr.fMode, fFlags);
    450502                        break;
    451503
    452                     if (RT_FAILURE(rc))
     504                    default:
     505                        /* Silently skip everything else. */
    453506                        break;
    454507                }
     508
     509                if (RT_SUCCESS(rc))
     510                    rc = dndTransferListRootAdd(pList, szPathAbs);
    455511            }
    456512        }
     
    465521}
    466522
     523/**
     524 * Appends an URI path to a DnD transfer list.
     525 *
     526 * @returns VBox status code.
     527 * @param   pList               Transfer list to append native path to.
     528 * @param   pcszPath            URI path to append.
     529 * @param   fFlags              Transfer list flags to use for appending.
     530 */
    467531static int dndTransferListAppendPathURI(PDNDTRANSFERLIST pList, const char *pcszPath, DNDTRANSFERLISTFLAGS fFlags)
    468532{
     
    579643        return VINF_SUCCESS;
    580644
     645    char **papszPathsTmp = NULL;
     646
     647    /* If URI data is being handed in, extract the paths first. */
     648    if (enmFmt == DNDTRANSFERLISTFMT_URI)
     649    {
     650        papszPathsTmp = (char **)RTMemAlloc(sizeof(char *) * cPaths);
     651        if (papszPathsTmp)
     652        {
     653            for (size_t i = 0; i < cPaths; i++)
     654                papszPathsTmp[i] = RTUriFilePath(papcszPaths[i]);
     655        }
     656        else
     657            rc = VERR_NO_MEMORY;
     658    }
     659
     660    if (RT_FAILURE(rc))
     661        return rc;
     662
    581663    /* If we don't have a root path set, try to find the common path of all handed-in paths. */
    582664    if (!pList->pszPathRootAbs)
    583665    {
    584         size_t cchRootPath = RTPathFindCommon(cPaths, papcszPaths);
     666        /* Can we work on the unmodified, handed-in data or do we need to use our temporary paths? */
     667        const char * const *papszPathTmp = enmFmt == DNDTRANSFERLISTFMT_NATIVE
     668                                         ? papcszPaths : papszPathsTmp;
     669
     670        size_t cchRootPath = 0; /* Length of root path in chars. */
     671        if (cPaths > 1)
     672        {
     673            cchRootPath = RTPathFindCommon(cPaths, papszPathTmp);
     674        }
     675        else
     676            cchRootPath = RTPathParentLength(papszPathTmp[0]);
     677
    585678        if (cchRootPath)
    586679        {
    587680            /* Just use the first path in the array as the reference. */
    588             char *pszRootPath = RTStrDupN(papcszPaths[0], cchRootPath);
     681            char *pszRootPath = RTStrDupN(papszPathTmp[0], cchRootPath);
    589682            if (pszRootPath)
    590683            {
    591684                LogRel2(("DnD: Determined root path is '%s'\n", pszRootPath));
    592                 rc = dndTransferListSetRootPath(pList, pszRootPath);
     685                rc = dndTransferListInitInternal(pList, pszRootPath);
    593686                RTStrFree(pszRootPath);
    594687            }
     
    596689                rc = VERR_NO_MEMORY;
    597690        }
    598     }
    599 
    600     /*
    601      * Go through the created list and make sure all entries have the same root path.
    602      */
    603     for (size_t i = 0; i < cPaths; i++)
    604     {
    605         rc = DnDTransferListAppendPath(pList, enmFmt, papcszPaths[i], fFlags);
    606         if (RT_FAILURE(rc))
    607             break;
     691        else
     692            rc = VERR_INVALID_PARAMETER;
     693    }
     694
     695    if (RT_SUCCESS(rc))
     696    {
     697        /*
     698         * Add all paths to the list.
     699         */
     700        for (size_t i = 0; i < cPaths; i++)
     701        {
     702            const char *pcszPath = enmFmt == DNDTRANSFERLISTFMT_NATIVE
     703                                 ? papcszPaths[i] : papszPathsTmp[i];
     704            rc = DnDTransferListAppendPath(pList, DNDTRANSFERLISTFMT_NATIVE, pcszPath, fFlags);
     705            if (RT_FAILURE(rc))
     706            {
     707                LogRel(("DnD: Adding path '%s' (format %#x, root '%s') to transfer list failed with %Rrc\n",
     708                        pcszPath, enmFmt, pList->pszPathRootAbs ? pList->pszPathRootAbs : "<None>", rc));
     709                break;
     710            }
     711        }
     712    }
     713
     714    if (papszPathsTmp)
     715    {
     716        for (size_t i = 0; i < cPaths; i++)
     717            RTStrFree(papszPathsTmp[i]);
     718        RTMemFree(papszPathsTmp);
    608719    }
    609720
     
    667778    AssertPtrReturn(pcbBuffer, VERR_INVALID_POINTER);
    668779
    669     char *pszString = NULL;
     780    char  *pszString = NULL;
     781    size_t cchString = 0;
     782
     783    const size_t cchSep = RTStrNLen(pcszSeparator, RTPATH_MAX);
    670784
    671785    /* Find out which root path to use. */
    672786    const char *pcszPathRootTmp = pcszPathBase ? pcszPathBase : pList->pszPathRootAbs;
    673     /* pcszPathRootTmp can be NULL*/
     787    /* pcszPathRootTmp can be NULL */
    674788
    675789    LogFlowFunc(("Using root path '%s'\n", pcszPathRootTmp ? pcszPathRootTmp : "<None>"));
     
    688802            rc = RTStrCopy(szPath, sizeof(szPath), pcszPathRootTmp);
    689803            AssertRCBreak(rc);
     804            cchString += RTStrNLen(pcszPathRootTmp, RTPATH_MAX);
    690805        }
    691806
     
    697812            char *pszPathURI = RTUriFileCreate(szPath);
    698813            AssertPtrBreakStmt(pszPathURI, rc = VERR_NO_MEMORY);
    699 
    700814            rc = RTStrAAppend(&pszString, pszPathURI);
     815            cchString += RTStrNLen(pszPathURI, RTPATH_MAX);
    701816            RTStrFree(pszPathURI);
    702817            AssertRCBreak(rc);
    703818        }
    704         else
    705         {
    706             rc = RTStrAAppend(&pszString, szPath);
    707             AssertRCBreak(rc);
     819        else /* Native */
     820        {
     821#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
     822            /* Convert paths to native path style. */
     823            rc = DnDPathConvert(szPath, sizeof(szPath), DNDPATHCONVERT_FLAGS_TO_DOS);
     824#endif
     825            if (RT_SUCCESS(rc))
     826            {
     827                rc = RTStrAAppend(&pszString, szPath);
     828                AssertRCBreak(rc);
     829
     830                cchString += RTStrNLen(szPath, RTPATH_MAX);
     831            }
    708832        }
    709833
    710834        rc = RTStrAAppend(&pszString, pcszSeparator);
    711835        AssertRCBreak(rc);
     836
     837        cchString += cchSep;
    712838    }
    713839
     
    715841    {
    716842        *ppszBuffer = pszString;
    717         *pcbBuffer  = pszString ? strlen(pszString) + 1 /* Include termination */ : 0;
     843        *pcbBuffer  = pszString ? cchString + 1 /* Include termination */ : 0;
    718844    }
    719845    else
     
    722848}
    723849
     850/**
     851 * Returns all root entries for a DnD transfer list.
     852 *
     853 * Note: Convenience function which uses the default DnD path separator.
     854 *
     855 * @returns VBox status code.
     856 * @param   pList               Transfer list to return root entries for.
     857 * @param   enmFmt              Which format to use for returning the entries.
     858 * @param   ppszBuffer          Where to return the allocated string on success. Needs to be free'd with RTStrFree().
     859 * @param   pcbBuffer           Where to return the size (in bytes) of the allocated string on success, including terminator.
     860 */
    724861int DnDTransferListGetRoots(PDNDTRANSFERLIST pList,
    725862                            DNDTRANSFERLISTFMT enmFmt, char **ppszBuffer, size_t *pcbBuffer)
     
    812949}
    813950
     951/**
     952 * Adds a root entry to a DnD transfer list.
     953 *
     954 * @returns VBox status code.
     955 * @param   pList               Transfer list to add root entry to.
     956 * @param   pcszRoot            Root entry to add.
     957 */
    814958static int dndTransferListRootAdd(PDNDTRANSFERLIST pList, const char *pcszRoot)
    815959{
    816960    int rc;
     961
     962    /** @todo Handle / reject double entries. */
     963
     964    /* Calculate the path to add as the destination path to our URI object. */
     965    const size_t idxPathToAdd = strlen(pList->pszPathRootAbs);
     966    AssertReturn(strlen(pcszRoot) > idxPathToAdd, VERR_INVALID_PARAMETER); /* Should never happen (tm). */
    817967
    818968    PDNDTRANSFERLISTROOT pRoot = (PDNDTRANSFERLISTROOT)RTMemAllocZ(sizeof(DNDTRANSFERLISTROOT));
    819969    if (pRoot)
    820970    {
    821         pRoot->pszPathRoot = RTStrDup(pcszRoot);
     971        const char *pcszRootIdx = &pcszRoot[idxPathToAdd];
     972
     973        LogFlowFunc(("pcszRoot=%s\n", pcszRootIdx));
     974
     975        pRoot->pszPathRoot = RTStrDup(pcszRootIdx);
    822976        if (pRoot->pszPathRoot)
    823977        {
     
    843997
    844998/**
    845  * Frees an internal DnD transfer root.
     999 * Removes (and destroys) a DnD transfer root entry.
    8461000 *
    8471001 * @param   pList               Transfer list to free root for.
     
    8621016}
    8631017
    864 
    865 #if 0
    866 /**
    867  * Appends a single URI path to a transfer list.
    868  *
    869  * @returns VBox status code.
    870  * @param   pList               Transfer list to append URI path to.
    871  * @param   pszURIPath          URI path to append.
    872  * @param   fFlags              Transfer list flags to use for appending.
    873  */
    874 int DnDTransferListURIAppendPath(PDNDTRANSFERLIST pList, const char *pszURIPath, DNDTRANSFERLISTFLAGS fFlags)
    875 {
    876     AssertPtrReturn(pList, VERR_INVALID_POINTER);
    877     AssertPtrReturn(pszURIPath, VERR_INVALID_POINTER);
    878     AssertReturn(!(fFlags & ~DNDTRANSFERLIST_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
    879 
    880     in rc;
    881 
    882     /* Query the path component of a file URI. If this hasn't a
    883      * file scheme, NULL is returned. */
    884     char *pszFilePath = RTUriFilePathEx(pszURIPath, RTPATH_STR_F_STYLE_UNIX, &pszFilePath, 0 /*cbPath*/, NULL /*pcchPath*/);
    885     LogFlowFunc(("pszPath=%s, pszFilePath=%s\n", pszFilePath));
    886     if (pszFilePath)
    887     {
    888         rc = DnDPathValidate(pszFilePath, false /* fMustExist */);
    889         if (RT_SUCCESS(rc))
    890         {
    891             uint32_t fPathConvert = DNDPATHCONVERT_FLAGS_TRANSPORT;
    892 #ifdef RT_OS_WINDOWS
    893             fPathConvert |= DNDPATHCONVERT_FLAGS_TO_DOS;
    894 #endif
    895             rc = DnDPathConvert(pszFilePath, strlen(pszFilePath) + 1, fPathConvert);
    896             if (RT_SUCCESS(rc))
    897             {
    898                 LogRel2(("DnD: Got URI data item '%s'\n", pszFilePath));
    899 
    900                 PDNDTRANSFERLISTROOT pRoot = (PDNDTRANSFERLISTROOT)RTMemAlloc(sizeof(DNDTRANSFERLISTROOT));
    901                 if (pRoot)
    902                 {
    903                     pRoot->pszPathRoot = pszFilePath;
    904 
    905                     RTListAppend(&pList->lstRoot, &pRoot->Node);
    906                     pList->cRoots++;
    907 
    908                 }
    909                 else
    910                     rc = VERR_NO_MEMORY;
    911             }
    912             else
    913                 LogRel(("DnD: Path conversion of URI data item '%s' failed with %Rrc\n", pszFilePath, rc));
    914         }
    915         else
    916             LogRel(("DnD: Path validation for URI data item '%s' failed with %Rrc\n", pszFilePath, rc));
    917 
    918         if (RT_FAILURE(rc))
    919             RTStrFree(pszFilePath);
    920     }
    921 
    922     LogFlowFuncLeaveRC(rc);
    923     return rc;
    924 }
    925 
    926 /**
    927  * Appends transfer list items from an URI string buffer.
    928  *
    929  * @returns VBox status code.
    930  * @param   pList               Transfer list to append list data to.
    931  * @param   pszURIPaths         String list to append.
    932  * @param   cbURIPaths          Size (in bytes) of string list to append.
    933  * @param   pcszSeparator       Separator string to use for separating strings of \a pszURIPathsAbs.
    934  * @param   fFlags              Transfer list flags to use for appending.
    935  */
    936 int DnDTransferListURIAppendFromBuffer(PDNDTRANSFERLIST pList,
    937                                        const char *pszURIPaths, size_t cbURIPaths,
    938                                        const char *pcszSeparator, DNDTRANSFERLISTFLAGS fFlags)
    939 {
    940     AssertPtrReturn(pList, VERR_INVALID_POINTER);
    941     AssertPtrReturn(pszURIPaths, VERR_INVALID_POINTER);
    942     AssertReturn(cbURIPaths, VERR_INVALID_PARAMETER);
    943     AssertReturn(!(fFlags & ~DNDTRANSFERLIST_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
    944 
    945     char **papszPaths = NULL;
    946     size_t cPaths = 0;
    947     int rc = RTStrSplit(pszURIPaths, cbURIPaths, pcszSeparator, &papszPaths, &cPaths);
    948     if (RT_SUCCESS(rc))
    949     {
    950         for (size_t i = 0; i < cPaths; i++)
    951         {
    952             rc = DnDTransferListURIAppendPath(pList, papszPaths[i], fFlags);
    953             if (RT_FAILURE(rc))
    954                 break;
    955         }
    956 
    957         for (size_t i = 0; i < cPaths; ++i)
    958             RTStrFree(papszPaths[i]);
    959         RTMemFree(papszPaths);
    960     }
    961 
    962     LogFlowFuncLeaveRC(rc);
    963     return rc;
    964 }
    965 #endif
  • trunk/src/VBox/GuestHost/DragAndDrop/testcase/tstDnDTransferList.cpp

    r85381 r85408  
    7171
    7272    /* Adding stuff. */
    73     RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS);
     73    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPath(&list, DNDTRANSFERLISTFMT_NATIVE, szPathWellKnown, DNDTRANSFERLIST_FLAGS_RECURSIVE), VINF_SUCCESS);
    7474    RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list));
    7575    RTTEST_CHECK(hTest, DnDTransferListObjCount(&list));
     
    113113                         "file:///dir1\r\n"
    114114                         "file:///dir%20with%20spaces\r\n";
     115
    115116    RTTEST_CHECK_RC(hTest, DnDTransferListAppendPathsFromBuffer(&list, DNDTRANSFERLISTFMT_URI, szURI, sizeof(szURI), "\r\n",
    116117                                                                DNDTRANSFERLIST_FLAGS_NONE), VINF_SUCCESS);
    117118    RTTEST_CHECK(hTest, DnDTransferListGetRootCount(&list) == 4);
     119    RTTEST_CHECK(hTest, RTStrCmp(DnDTransferListGetRootPathAbs(&list), RTPATH_SLASH_STR) == 0);
    118120    RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "/native/base/path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS);
     121    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf);
     122    RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "\\windows\\path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS);
     123    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf);
     124    RTTEST_CHECK_RC(hTest, DnDTransferListGetRootsEx(&list, DNDTRANSFERLISTFMT_NATIVE, "\\\\windows\\\\path", "\n", &pszBuf, &cbBuf), VINF_SUCCESS);
    119125    RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Roots (URI, new base):\n%s\n", pszBuf);
    120126    RTStrFree(pszBuf);
Note: See TracChangeset for help on using the changeset viewer.

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