RTCList<RTCString, RTCString *>
RTCString::split(const RTCString &a_rstrSep, SplitMode mode /* = RemoveEmptyParts */) const
{
    RTCList<RTCString> strRet;
    if (!m_psz)
        return strRet;
    if (a_rstrSep.isEmpty())
    {
        strRet.append(RTCString(m_psz));
        return strRet;
    }

    size_t      cch    = m_cch;
    char const *pszTmp = m_psz;
    while (cch > 0)
    {
        char const *pszNext = strstr(pszTmp, a_rstrSep.c_str());
        if (!pszNext)
        {
            strRet.append(RTCString(pszTmp, cch));
            break;
        }
        size_t cchNext = pszNext - pszTmp;
        if (   cchNext > 0
            || mode == KeepEmptyParts)
            strRet.append(RTCString(pszTmp, cchNext));
        pszTmp += cchNext + a_rstrSep.length();
        cch    -= cchNext + a_rstrSep.length();
    }

    return strRet;
}
/* static */
RTCString
RTCString::joinEx(const RTCList<RTCString, RTCString *> &a_rList,
                  const RTCString &a_rstrPrefix /* = "" */,
                  const RTCString &a_rstrSep /* = "" */)
{
    RTCString strRet;
    if (a_rList.size() > 1)
    {
        /* calc the required size */
        size_t cbNeeded = a_rstrSep.length() * (a_rList.size() - 1) + 1;
        cbNeeded += a_rstrPrefix.length() * (a_rList.size() - 1) + 1;
        for (size_t i = 0; i < a_rList.size(); ++i)
            cbNeeded += a_rList.at(i).length();
        strRet.reserve(cbNeeded);

        /* do the appending. */
        for (size_t i = 0; i < a_rList.size() - 1; ++i)
        {
            if (a_rstrPrefix.isNotEmpty())
                strRet.append(a_rstrPrefix);
            strRet.append(a_rList.at(i));
            strRet.append(a_rstrSep);
        }
        strRet.append(a_rList.last());
    }
    /* special case: one list item. */
    else if (a_rList.size() > 0)
    {
        if (a_rstrPrefix.isNotEmpty())
            strRet.append(a_rstrPrefix);
        strRet.append(a_rList.last());
    }

    return strRet;
}
/* static */
GuestDnDMIMEList GuestDnD::toFormatList(const com::Utf8Str &strFormats)
{
    GuestDnDMIMEList lstFormats;
    RTCList<RTCString> lstFormatsTmp = strFormats.split("\r\n");

    for (size_t i = 0; i < lstFormatsTmp.size(); i++)
        lstFormats.push_back(com::Utf8Str(lstFormatsTmp.at(i)));

    return lstFormats;
}
Пример #4
0
int DnDURIList::AppendNativePathsFromList(const RTCList<RTCString> &lstNativePaths,
                                          uint32_t fFlags)
{
    int rc = VINF_SUCCESS;

    for (size_t i = 0; i < lstNativePaths.size(); i++)
    {
        const RTCString &strPath = lstNativePaths.at(i);
        rc = AppendNativePath(strPath.c_str(), fFlags);
        if (RT_FAILURE(rc))
            break;
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
/* static */
std::vector<DnDAction_T> GuestDnD::toMainActions(uint32_t uActions)
{
    std::vector<DnDAction_T> vecActions;

    /* For now it doesn't seems useful to allow a
     * link action between host & guest. Maybe later! */
    RTCList<DnDAction_T> lstActions;
    if (hasDnDCopyAction(uActions))
        lstActions.append(DnDAction_Copy);
    if (hasDnDMoveAction(uActions))
        lstActions.append(DnDAction_Move);

    for (size_t i = 0; i < lstActions.size(); ++i)
        vecActions.push_back(lstActions.at(i));

    return vecActions;
}
Пример #6
0
int DnDURIList::RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags)
{
    Assert(fFlags == 0); RT_NOREF1(fFlags);
    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
    AssertReturn(cbData, VERR_INVALID_PARAMETER);

    if (!RTStrIsValidEncoding(static_cast<const char *>(pvData)))
        return VERR_INVALID_PARAMETER;

    RTCList<RTCString> lstURI =
        RTCString(static_cast<const char *>(pvData), cbData - 1).split("\r\n");
    if (lstURI.isEmpty())
        return VINF_SUCCESS;

    int rc = VINF_SUCCESS;

    for (size_t i = 0; i < lstURI.size(); ++i)
    {
        /* Query the path component of a file URI. If this hasn't a
         * file scheme, NULL is returned. */
        const char *pszURI = lstURI.at(i).c_str();
        char *pszFilePath = RTUriFilePath(pszURI);
#ifdef DEBUG_andy
        LogFlowFunc(("pszURI=%s, pszFilePath=%s\n", pszURI, pszFilePath));
#endif
        if (pszFilePath)
        {
            rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath));
            if (RT_SUCCESS(rc))
            {
                m_lstRoot.append(pszFilePath);
                m_cTotal++;
            }

            RTStrFree(pszFilePath);
        }
        else
            rc = VERR_INVALID_PARAMETER;

        if (RT_FAILURE(rc))
            break;
    }

    return rc;
}
/* static */
GuestDnDMIMEList GuestDnD::toFilteredFormatList(const GuestDnDMIMEList &lstFormatsSupported, const com::Utf8Str &strFormatsWanted)
{
    GuestDnDMIMEList lstFmt;

    RTCList<RTCString> lstFormats = strFormatsWanted.split("\r\n");
    size_t i = 0;
    while (i < lstFormats.size())
    {
        /* Only keep allowed format types. */
        if (std::find(lstFormatsSupported.begin(),
                      lstFormatsSupported.end(), lstFormats.at(i)) != lstFormatsSupported.end())
        {
            lstFmt.push_back(lstFormats[i]);
        }
        i++;
    }

    return lstFmt;
}
Пример #8
0
void GluePrintErrorInfo(const com::ErrorInfo &info)
{
    bool haveResultCode = false;
#if defined (RT_OS_WIN)
    haveResultCode = info.isFullAvailable();
    bool haveComponent = true;
    bool haveInterfaceID = true;
#else /* defined (RT_OS_WIN) */
    haveResultCode = true;
    bool haveComponent = info.isFullAvailable();
    bool haveInterfaceID = info.isFullAvailable();
#endif

    Utf8Str str;
    RTCList<Utf8Str> comp;

    Bstr bstrDetailsText = info.getText();
    if (!bstrDetailsText.isEmpty())
        str = Utf8StrFmt("%ls\n",
                         bstrDetailsText.raw());
    if (haveResultCode)
        comp.append(Utf8StrFmt("code %Rhrc (0x%RX32)",
                               info.getResultCode(),
                               info.getResultCode()));
    if (haveComponent)
        comp.append(Utf8StrFmt("component %ls",
                               info.getComponent().raw()));
    if (haveInterfaceID)
        comp.append(Utf8StrFmt("interface %ls",
                               info.getInterfaceName().raw()));
    if (!info.getCalleeName().isEmpty())
        comp.append(Utf8StrFmt("callee %ls",
                               info.getCalleeName().raw()));

    if (comp.size() > 0)
    {
        str += "Details: ";
        for (size_t i = 0; i < comp.size() - 1; ++i)
            str += comp.at(i) + ", ";
        str += comp.last();
        str += "\n";
    }

    // print and log
    RTMsgError("%s", str.c_str());
    Log(("ERROR: %s", str.c_str()));
}
Пример #9
0
int GuestEnvironment::Set(const Utf8Str &strPair)
{
    RTCList<RTCString> listPair = strPair.split("=", RTCString::KeepEmptyParts);
    /* Skip completely empty pairs. Note that we still need pairs with a valid
     * (set) key and an empty value. */
    if (listPair.size() <= 1)
        return VINF_SUCCESS;

    int rc = VINF_SUCCESS;
    size_t p = 0;
    while (p < listPair.size() && RT_SUCCESS(rc))
    {
        Utf8Str strKey = listPair.at(p++);
        if (   strKey.isEmpty()
            || strKey.equals("=")) /* Skip pairs with empty keys (e.g. "=FOO"). */
        {
            break;
        }
        Utf8Str strValue;
        if (p < listPair.size()) /* Does the list also contain a value? */
            strValue = listPair.at(p++);

#ifdef DEBUG
        LogFlowFunc(("strKey=%s, strValue=%s\n",
                     strKey.c_str(), strValue.c_str()));
#endif
        rc = Set(strKey, strValue);
    }

    return rc;
}
Пример #10
0
static int vbglR3DnDHGProcessURIMessages(uint32_t   uClientId,
                                         uint32_t  *puScreenId,
                                         char      *pszFormat,
                                         uint32_t   cbFormat,
                                         uint32_t  *pcbFormatRecv,
                                         void     **ppvData,
                                         uint32_t   cbData,
                                         size_t    *pcbDataRecv)
{
    /* Make a string list out of the uri data. */
    RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n");
    if (uriList.isEmpty())
        return VINF_SUCCESS;

    uint32_t cbTmpData = _1M * 10;
    void *pvTmpData = RTMemAlloc(cbTmpData);
    if (!pvTmpData)
        return VERR_NO_MEMORY;

    /* Create and query the drop target directory. */
    char pszDropDir[RTPATH_MAX];
    int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir));
    if (RT_FAILURE(rc))
    {
        RTMemFree(pvTmpData);
        return rc;
    }

    /* Patch the old drop data with the new drop directory, so the drop target
     * can find the files. */
    RTCList<RTCString> guestUriList;
    for (size_t i = 0; i < uriList.size(); ++i)
    {
        const RTCString &strUri = uriList.at(i);
        /* Query the path component of a file URI. If this hasn't a
         * file scheme, null is returned. */
        if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO))
        {
            RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath);
            char *pszNewUri = RTUriFileCreate(strFullPath.c_str());
            if (pszNewUri)
            {
                guestUriList.append(pszNewUri);
                RTStrFree(pszNewUri);
            }
        }
        else
            guestUriList.append(strUri);
    }

    /* Cleanup the old data and write the new data back to the event. */
    RTMemFree(*ppvData);
    RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n";
    *ppvData = RTStrDupN(newData.c_str(), newData.length());
    *pcbDataRecv = newData.length() + 1;

    /* Lists for holding created files & directories in the case of a
     * rollback. */
    RTCList<RTCString> guestDirList;
    RTCList<RTCString> guestFileList;
    char pszPathname[RTPATH_MAX];
    uint32_t cbPathname = 0;
    bool fLoop = true;
    do
    {
        uint32_t uNextMsg;
        uint32_t cNextParms;
        rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false);
        DO(("%Rrc - %d\n", rc , uNextMsg));
        if (RT_SUCCESS(rc))
        {
            switch(uNextMsg)
            {
                case DragAndDropSvc::HOST_DND_HG_SND_DIR:
                {
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendDirMessage(uClientId,
                                                          pszPathname,
                                                          sizeof(pszPathname),
                                                          &cbPathname,
                                                          &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc));
                        char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname);
                        rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0);
                        if (!guestDirList.contains(pszNewDir))
                            guestDirList.append(pszNewDir);
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_SND_FILE:
                {
                    uint32_t cbDataRecv;
                    uint32_t fMode = 0;
                    rc = vbglR3DnDHGProcessSendFileMessage(uClientId,
                                                           pszPathname,
                                                           sizeof(pszPathname),
                                                           &cbPathname,
                                                           pvTmpData,
                                                           cbTmpData,
                                                           &cbDataRecv,
                                                           &fMode);
                    if (RT_SUCCESS(rc))
                    {
                        char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname);
                        DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc));
                        RTFILE hFile;
                        rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL);
                            if (RT_SUCCESS(rc))
                            {
                                rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0);
                                /* Valid UNIX mode? */
                                if (   RT_SUCCESS(rc)
                                    && (fMode & RTFS_UNIX_MASK))
                                    rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
                            }
                            RTFileClose(hFile);
                            if (!guestFileList.contains(pszNewFile))
                                guestFileList.append(pszNewFile);
                        }
                    }
                    break;
                }
                case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
                {
                    rc = vbglR3DnDHGProcessCancelMessage(uClientId);
                    if (RT_SUCCESS(rc))
                        rc = VERR_CANCELLED;
                    /* Break out of the loop. */
                }
                default: fLoop = false; break;
            }
        } else
        {
            if (rc == VERR_NO_DATA)
                rc = VINF_SUCCESS;
            break;
        }
    }while(fLoop);

    RTMemFree(pvTmpData);
    /* Cleanup on failure or if the user has canceled. */
    if (RT_FAILURE(rc))
    {
        /* Remove any stuff created. */
        for (size_t i = 0; i < guestFileList.size(); ++i)
            RTFileDelete(guestFileList.at(i).c_str());
        for (size_t i = 0; i < guestDirList.size(); ++i)
            RTDirRemove(guestDirList.at(i).c_str());
        RTDirRemove(pszDropDir);
    }

    return rc;
}
Пример #11
0
/*
 * This class is a meta message class. It doesn't consist of any own message
 * data, but handle the meta info, the data itself as well as any files or
 * directories which have to be transfered to the guest.
 */
DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms,
                                           VBOXHGCMSVCPARM paParms[],
                                           PFNDNDPROGRESS pfnProgressCallback,
                                           void *pvProgressUser)
    : m_cbTotal(0)
    , m_cbTransfered(0)
    , m_pfnProgressCallback(pfnProgressCallback)
    , m_pvProgressUser(pvProgressUser)
{
    if (cParms < 5) /* Paranoia. */
        return;

    const char *pszFormat = static_cast<const char*>(paParms[1].u.pointer.addr);
    uint32_t cbFormat = paParms[1].u.pointer.size;

    int rc = VINF_SUCCESS;
    RTCString strNewURIs;

    /* Do we need to build up a file tree? */
    if (DnDMIMEHasFileURLs(pszFormat, cbFormat))
    {
        const char *pszList = static_cast<const char*>(paParms[3].u.pointer.addr);
        AssertPtr(pszList);
        uint32_t cbList = paParms[3].u.pointer.size;
        Assert(cbList);

        LogFlowFunc(("Old data (%RU32 bytes): '%s'\n", cbList, pszList));

        /* The list is separated by newline (even if only one file is listed). */
        RTCList<RTCString> lstURIOrg
            = RTCString(pszList, cbList).split("\r\n");
        if (!lstURIOrg.isEmpty())
        {
            rc = m_lstURI.AppendURIPathsFromList(lstURIOrg, 0 /* fFlags */);
            if (RT_SUCCESS(rc))
            {
                /* Add the total size of all meta data + files transferred to
                 * the message's total byte count. */
                m_cbTotal += m_lstURI.TotalBytes();

                /* We have to change the actual DnD data. Remove any host paths and
                 * just decode the filename into the new data. The Guest Additions will
                 * add the correct path again before sending the DnD drop event to
                 * some window. */
                strNewURIs = m_lstURI.RootToString();

                /* Note: We don't delete the old pointer here, cause this is done
                 *       by the caller. We just use the RTString data, which has the
                 *       scope of this ctor. This is enough cause the data is copied in
                 *       the DnDHGSendDataMessagePrivate anyway. */
                paParms[3].u.pointer.addr = (void *)strNewURIs.c_str();
                paParms[3].u.pointer.size = (uint32_t)(strNewURIs.length() + 1);
                paParms[4].u.uint32       = (uint32_t)(strNewURIs.length() + 1);

                LogFlowFunc(("Set new data (%RU32 bytes): '%s'\n",
                            paParms[3].u.pointer.size,
                            (const char*)paParms[3].u.pointer.addr));
            }
        }
    }

    /* Add the size of the data to the todo list. */
    m_cbTotal += paParms[4].u.uint32;
    LogFlowFunc(("cbTotal=%zu\n", m_cbTotal));

    /* The first message is the meta info for the data and the data itself. */
    m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms,
                                                     &DnDHGSendDataMessage::progressCallback, this);
}
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP VBoxDnDDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    ULONG lIndex;
    if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
        return DV_E_FORMATETC;
    if (lIndex >= mcFormats) /* Paranoia. */
        return DV_E_FORMATETC;

    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));

    FORMATETC *pThisFormat = &mpFormatEtc[lIndex];
    AssertPtr(pThisFormat);

    STGMEDIUM *pThisMedium = &mpStgMedium[lIndex];
    AssertPtr(pThisMedium);

    HRESULT hr = DV_E_FORMATETC;

    LogFlowFunc(("mStatus=%ld\n", mStatus));
    if (mStatus == Dropping)
    {
        LogFlowFunc(("Waiting for event ...\n"));
        int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT);
        LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus));
    }

    if (mStatus == Dropped)
    {
        LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                     pThisFormat->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                     pThisFormat->tymed, pThisFormat->dwAspect));
        LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                     mstrFormat.c_str(), mpvData, mcbData));

        if (mstrFormat.equalsIgnoreCase("text/uri-list"))
        {
            RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
            RTCList<RTCString> lstFiles;
            for (size_t i = 0; i < lstFilesURI.size(); i++)
            {
                /* Extract path from URI. */
                char *pszPath = RTUriPath(lstFilesURI.at(i).c_str());
                if (   pszPath
                    && strlen(pszPath) > 1)
                {
                    pszPath++; /** @todo Skip first '/' (part of URI). Correct? */
                    pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */);
                    lstFiles.append(pszPath);
                }
            }
#ifdef DEBUG
            LogFlowFunc(("Files (%zu)\n", lstFiles.size()));
            for (size_t i = 0; i < lstFiles.size(); i++)
                LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
#endif

#if 0
            if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                && (pFormatEtc->cfFormat == CF_FILECONTENTS))
            {

            }
            else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                      && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                      && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
            {

            }
            else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
            {
                HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
                DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
                AssertPtr(pdwEffect);
                *pdwEffect = DROPEFFECT_COPY;
                GlobalUnlock(hData);

                pMedium->hGlobal = hData;
                pMedium->tymed = TYMED_HGLOBAL;
            }
            else
#endif
                 if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_TEXT))
            {
                pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
                if (pMedium->hGlobal)
                {
                    /** @todo Not working yet -- needs URI to plain ASCII conversion. */

                    char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
                    memcpy(pcDst, mpvData, mcbData);
                    pcDst[mcbData] = '\0';
                    GlobalUnlock(pMedium->hGlobal);

                    hr = S_OK;
                }
            }
            else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_HDROP))
            {
                int rc = VINF_SUCCESS;

                size_t cchFiles = 0; /* Number of ASCII characters. */
                for (size_t i = 0; i < lstFiles.size(); i++)
                {
                    cchFiles += strlen(lstFiles.at(i).c_str());
                    cchFiles += 1; /* Terminating '\0'. */
                }

                size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
                DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
                if (pBuf)
                {
                    pBuf->pFiles = sizeof(DROPFILES);
                    pBuf->fWide = 1; /* We use unicode. Always. */

                    uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
                    AssertPtr(pCurFile);

                    for (size_t i = 0; i < lstFiles.size() && RT_SUCCESS(rc); i++)
                    {
                        size_t cchCurFile;
                        PRTUTF16 pwszFile;
                        rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
                        if (RT_SUCCESS(rc))
                        {
                            cchCurFile = RTUtf16Len(pwszFile);
                            Assert(cchCurFile);
                            memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
                            RTUtf16Free(pwszFile);
                        }
                        else
                            break;

                        pCurFile += cchCurFile * sizeof(RTUTF16);

                        /* Terminate current file name. */
                        *pCurFile = L'\0';
                        pCurFile += sizeof(RTUTF16);
                    }

                    if (RT_SUCCESS(rc))
                    {
                        *pCurFile = L'\0'; /* Final list terminator. */

                        pMedium->tymed = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                       | GMEM_MOVEABLE
                                                       | GMEM_DDESHARE, cbBuf);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pMem = GlobalLock(pMedium->hGlobal);
                            if (pMem)
                            {
                                memcpy(pMem, pBuf, cbBuf);
                                GlobalUnlock(pMedium->hGlobal);

                                hr = S_OK;
                            }
                        }
                    }

                    RTMemFree(pBuf);
                }
                else
                    rc = VERR_NO_MEMORY;

                if (RT_FAILURE(rc))
                    hr = DV_E_FORMATETC;
            }
        }
    }

    if (FAILED(hr))
    {
        LogFlowFunc(("Copying medium ...\n"));
        switch (pThisMedium->tymed)
        {

        case TYMED_HGLOBAL:
            pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                         pThisFormat->cfFormat, NULL);
            break;

        default:
            break;
        }

        pMedium->tymed          = pThisFormat->tymed;
        pMedium->pUnkForRelease = NULL;
    }

    LogFlowFunc(("hr=%Rhrc\n", hr));
    return hr;
}
Пример #13
0
static void test1(RTTEST hTest)
{
    RTTestSub(hTest, "Basics");

#define CHECK(expr) RTTESTI_CHECK(expr)
#define CHECK_DUMP(expr, value) \
    do { \
        if (!(expr)) \
            RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \
    } while (0)

#define CHECK_DUMP_I(expr) \
    do { \
        if (!(expr)) \
            RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \
    } while (0)
#define CHECK_EQUAL(Str, szExpect) \
    do { \
        if (!(Str).equals(szExpect)) \
            RTTestIFailed("line %u: expected \"%s\" got \"%s\"", __LINE__, szExpect, (Str).c_str()); \
    } while (0)
#define CHECK_EQUAL_I(iRes, iExpect) \
    do { \
        if (iRes != iExpect) \
            RTTestIFailed("line %u: expected \"%zd\" got \"%zd\"", __LINE__, iExpect, iRes); \
    } while (0)

    RTCString empty;
    CHECK(empty.length() == 0);
    CHECK(empty.capacity() == 0);

    RTCString sixbytes("12345");
    CHECK(sixbytes.length() == 5);
    CHECK(sixbytes.capacity() == 6);

    sixbytes.append(RTCString("678"));
    CHECK(sixbytes.length() == 8);
    CHECK(sixbytes.capacity() >= 9);

    sixbytes.append("9a");
    CHECK(sixbytes.length() == 10);
    CHECK(sixbytes.capacity() >= 11);

    char *psz = sixbytes.mutableRaw();
        // 123456789a
        //       ^
        // 0123456
    psz[6] = '\0';
    sixbytes.jolt();
    CHECK(sixbytes.length() == 6);
    CHECK(sixbytes.capacity() == 7);

    RTCString morebytes("tobereplaced");
    morebytes = "newstring ";
    morebytes.append(sixbytes);

    CHECK_DUMP(morebytes == "newstring 123456", morebytes.c_str());

    RTCString third(morebytes);
    third.reserve(100 * 1024);      // 100 KB
    CHECK_DUMP(third == "newstring 123456", morebytes.c_str() );
    CHECK(third.capacity() == 100 * 1024);
    CHECK(third.length() == morebytes.length());          // must not have changed

    RTCString copy1(morebytes);
    RTCString copy2 = morebytes;
    CHECK(copy1 == copy2);

    copy1 = NULL;
    CHECK(copy1.length() == 0);

    copy1 = "";
    CHECK(copy1.length() == 0);

    CHECK(RTCString("abc") <  RTCString("def"));
    CHECK(RTCString("") <  RTCString("def"));
    CHECK(RTCString("abc") > RTCString(""));
    CHECK(RTCString("abc") != RTCString("def"));
    CHECK_DUMP_I(RTCString("def") > RTCString("abc"));
    CHECK(RTCString("abc") == RTCString("abc"));
    CHECK(RTCString("").compare("") == 0);
    CHECK(RTCString("").compare(NULL) == 0);
    CHECK(RTCString("").compare("a") < 0);
    CHECK(RTCString("a").compare("") > 0);
    CHECK(RTCString("a").compare(NULL) > 0);

    CHECK(RTCString("abc") <  "def");
    CHECK(RTCString("abc") != "def");
    CHECK_DUMP_I(RTCString("def") > "abc");
    CHECK(RTCString("abc") == "abc");

    CHECK(RTCString("abc").equals("abc"));
    CHECK(!RTCString("abc").equals("def"));
    CHECK(RTCString("abc").equalsIgnoreCase("Abc"));
    CHECK(RTCString("abc").equalsIgnoreCase("ABc"));
    CHECK(RTCString("abc").equalsIgnoreCase("ABC"));
    CHECK(!RTCString("abc").equalsIgnoreCase("dBC"));
    CHECK(RTCString("").equals(""));
    CHECK(RTCString("").equals(NULL));
    CHECK(!RTCString("").equals("a"));
    CHECK(!RTCString("a").equals(""));
    CHECK(!RTCString("a").equals(NULL));
    CHECK(RTCString("").equalsIgnoreCase(""));
    CHECK(RTCString("").equalsIgnoreCase(NULL));
    CHECK(!RTCString("").equalsIgnoreCase("a"));
    CHECK(!RTCString("a").equalsIgnoreCase(""));

    copy2.setNull();
    for (int i = 0; i < 100; ++i)
    {
        copy2.reserve(50);      // should be ignored after 50 loops
        copy2.append("1");
    }
    CHECK(copy2.length() == 100);

    copy2.setNull();
    for (int i = 0; i < 100; ++i)
    {
        copy2.reserve(50);      // should be ignored after 50 loops
        copy2.append('1');
    }
    CHECK(copy2.length() == 100);

    /* printf */
    RTCString StrFmt;
    CHECK(StrFmt.printf("%s-%s-%d", "abc", "def", 42).equals("abc-def-42"));
    test1Hlp1("abc-42-def", "%s-%d-%s", "abc", 42, "def");
    test1Hlp1("", "");
    test1Hlp1("1", "1");
    test1Hlp1("foobar", "%s", "foobar");

    /* substring constructors */
    RTCString SubStr1("", (size_t)0);
    CHECK_EQUAL(SubStr1, "");

    RTCString SubStr2("abcdef", 2);
    CHECK_EQUAL(SubStr2, "ab");

    RTCString SubStr3("abcdef", 1);
    CHECK_EQUAL(SubStr3, "a");

    RTCString SubStr4("abcdef", 6);
    CHECK_EQUAL(SubStr4, "abcdef");

    RTCString SubStr5("abcdef", 7);
    CHECK_EQUAL(SubStr5, "abcdef");


    RTCString SubStrBase("abcdef");

    RTCString SubStr10(SubStrBase, 0);
    CHECK_EQUAL(SubStr10, "abcdef");

    RTCString SubStr11(SubStrBase, 1);
    CHECK_EQUAL(SubStr11, "bcdef");

    RTCString SubStr12(SubStrBase, 1, 1);
    CHECK_EQUAL(SubStr12, "b");

    RTCString SubStr13(SubStrBase, 2, 3);
    CHECK_EQUAL(SubStr13, "cde");

    RTCString SubStr14(SubStrBase, 2, 4);
    CHECK_EQUAL(SubStr14, "cdef");

    RTCString SubStr15(SubStrBase, 2, 5);
    CHECK_EQUAL(SubStr15, "cdef");

    /* substr() and substrCP() functions */
    RTCString strTest("");
    CHECK_EQUAL(strTest.substr(0), "");
    CHECK_EQUAL(strTest.substrCP(0), "");
    CHECK_EQUAL(strTest.substr(1), "");
    CHECK_EQUAL(strTest.substrCP(1), "");

    /* now let's have some non-ASCII to chew on */
    strTest = "abcdefßäbcdef";
            // 13 codepoints, but 15 bytes (excluding null terminator);
            // "ß" and "ä" consume two bytes each
    CHECK_EQUAL(strTest.substr(0),   strTest.c_str());
    CHECK_EQUAL(strTest.substrCP(0), strTest.c_str());

    CHECK_EQUAL(strTest.substr(2),   "cdefßäbcdef");
    CHECK_EQUAL(strTest.substrCP(2), "cdefßäbcdef");

    CHECK_EQUAL(strTest.substr(2, 2),   "cd");
    CHECK_EQUAL(strTest.substrCP(2, 2), "cd");

    CHECK_EQUAL(strTest.substr(6),   "ßäbcdef");
    CHECK_EQUAL(strTest.substrCP(6), "ßäbcdef");

    CHECK_EQUAL(strTest.substr(6, 2),   "ß");           // UTF-8 "ß" consumes two bytes
    CHECK_EQUAL(strTest.substrCP(6, 1), "ß");

    CHECK_EQUAL(strTest.substr(8),   "äbcdef");         // UTF-8 "ß" consumes two bytes
    CHECK_EQUAL(strTest.substrCP(7), "äbcdef");

    CHECK_EQUAL(strTest.substr(8, 3),   "äb");          // UTF-8 "ä" consumes two bytes
    CHECK_EQUAL(strTest.substrCP(7, 2), "äb");

    CHECK_EQUAL(strTest.substr(14, 1),   "f");
    CHECK_EQUAL(strTest.substrCP(12, 1), "f");

    CHECK_EQUAL(strTest.substr(15, 1),   "");
    CHECK_EQUAL(strTest.substrCP(13, 1), "");

    CHECK_EQUAL(strTest.substr(16, 1),   "");
    CHECK_EQUAL(strTest.substrCP(15, 1), "");

    /* and check cooperation with find() */
    size_t pos = strTest.find("ß");
    CHECK_EQUAL(strTest.substr(pos), "ßäbcdef");

    /* check find() */
    CHECK_EQUAL_I(strTest.find("f"), 5);
    CHECK_EQUAL_I(strTest.find("f", 0), 5);
    CHECK_EQUAL_I(strTest.find("f", 3), 5);
    CHECK_EQUAL_I(strTest.find("f", 6), 14);
    CHECK_EQUAL_I(strTest.find("f", 9), 14);
    CHECK_EQUAL_I(strTest.substr(pos).find("d"), 6);

    /* split */
    RTCList<RTCString> spList1 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::RemoveEmptyParts);
    RTTESTI_CHECK(spList1.size() == 3);
    for (size_t i = 0; i < spList1.size(); ++i)
        RTTESTI_CHECK(spList1.at(i) == "abcdef");
    RTCList<RTCString> spList2 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::KeepEmptyParts);
    RTTESTI_CHECK_RETV(spList2.size() == 5);
    RTTESTI_CHECK(spList2.at(0) == "");
    RTTESTI_CHECK(spList2.at(1) == "abcdef");
    RTTESTI_CHECK(spList2.at(2) == "abcdef");
    RTTESTI_CHECK(spList2.at(3) == "");
    RTTESTI_CHECK(spList2.at(4) == "abcdef");
    RTCList<RTCString> spList3 = RTCString().split("##", RTCString::KeepEmptyParts);
    RTTESTI_CHECK(spList3.size() == 0);
    RTCList<RTCString> spList4 = RTCString().split("");
    RTTESTI_CHECK(spList4.size() == 0);
    RTCList<RTCString> spList5 = RTCString("abcdef").split("");
    RTTESTI_CHECK_RETV(spList5.size() == 1);
    RTTESTI_CHECK(spList5.at(0) == "abcdef");

    /* join */
    RTCList<RTCString> jnList;
    strTest = RTCString::join(jnList);
    RTTESTI_CHECK(strTest == "");
    strTest = RTCString::join(jnList, "##");
    RTTESTI_CHECK(strTest == "");

    jnList.append("abcdef");
    strTest = RTCString::join(jnList, "##");
    RTTESTI_CHECK(strTest == "abcdef");

    jnList.append("abcdef");
    strTest = RTCString::join(jnList, ";");
    RTTESTI_CHECK(strTest == "abcdef;abcdef");

    for (size_t i = 0; i < 3; ++i)
        jnList.append("abcdef");
    strTest = RTCString::join(jnList);
    RTTESTI_CHECK(strTest == "abcdefabcdefabcdefabcdefabcdef");
    strTest = RTCString::join(jnList, "##");
    RTTESTI_CHECK(strTest == "abcdef##abcdef##abcdef##abcdef##abcdef");

    /* special constructor and assignment arguments */
    RTCString StrCtor1("");
    RTTESTI_CHECK(StrCtor1.isEmpty());
    RTTESTI_CHECK(StrCtor1.length() == 0);

    RTCString StrCtor2(NULL);
    RTTESTI_CHECK(StrCtor2.isEmpty());
    RTTESTI_CHECK(StrCtor2.length() == 0);

    RTCString StrCtor1d(StrCtor1);
    RTTESTI_CHECK(StrCtor1d.isEmpty());
    RTTESTI_CHECK(StrCtor1d.length() == 0);

    RTCString StrCtor2d(StrCtor2);
    RTTESTI_CHECK(StrCtor2d.isEmpty());
    RTTESTI_CHECK(StrCtor2d.length() == 0);

    for (unsigned i = 0; i < 2; i++)
    {
        RTCString StrAssign;
        if (i) StrAssign = "abcdef";
        StrAssign = (char *)NULL;
        RTTESTI_CHECK(StrAssign.isEmpty());
        RTTESTI_CHECK(StrAssign.length() == 0);

        if (i) StrAssign = "abcdef";
        StrAssign = "";
        RTTESTI_CHECK(StrAssign.isEmpty());
        RTTESTI_CHECK(StrAssign.length() == 0);

        if (i) StrAssign = "abcdef";
        StrAssign = StrCtor1;
        RTTESTI_CHECK(StrAssign.isEmpty());
        RTTESTI_CHECK(StrAssign.length() == 0);

        if (i) StrAssign = "abcdef";
        StrAssign = StrCtor2;
        RTTESTI_CHECK(StrAssign.isEmpty());
        RTTESTI_CHECK(StrAssign.length() == 0);
    }

#undef CHECK
#undef CHECK_DUMP
#undef CHECK_DUMP_I
#undef CHECK_EQUAL
}
Пример #14
0
/*
 * This class is a meta message class. It doesn't consist of any own message
 * data, but handle the meta info, the data itself as well any files or
 * directories which have to be transfered to the guest.
 */
DnDHGSendDataMessage::DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser)
  : m_cbAll(0)
  , m_cbTransfered(0)
  , m_pfnProgressCallback(pfnProgressCallback)
  , m_pvProgressUser(pvProgressUser)
{
    RTCString strNewUris;
    /* Check the format for any uri type. */
    if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), paParms[1].u.pointer.size))
    {
        DO(("old data '%s'\n", (char*)paParms[3].u.pointer.addr));
        /* The list is separated by newline (Even if only one file is
         * listed). */
        RTCList<RTCString> oldUriList = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr), paParms[3].u.pointer.size).split("\r\n");
        if (!oldUriList.isEmpty())
        {
            RTCList<RTCString> newUriList;
            for (size_t i = 0; i < oldUriList.size(); ++i)
            {
                const RTCString &strUri = oldUriList.at(i);
                /* Query the path component of a file URI. If this hasn't a
                 * file scheme null is returned. */
                if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO))
                {
                    /* Add the path to our internal file list (recursive in
                     * the case of a directory). */
                    if (char *pszFilename = RTPathFilename(pszFilePath))
                    {
                        char *pszNewUri = RTUriFileCreate(pszFilename);
                        if (pszNewUri)
                        {
                            newUriList.append(pszNewUri);
                            RTStrFree(pszNewUri);
                            buildFileTree(pszFilePath, pszFilename - pszFilePath);
                        }
                    }
                    RTStrFree(pszFilePath);
                }
                else
                    newUriList.append(strUri);
            }
            /* We have to change the actual DnD data. Remove any host paths and
             * just decode the filename into the new data. The guest tools will
             * add the correct path again, before sending the DnD drop event to
             * some window. */
            strNewUris = RTCString::join(newUriList, "\r\n") + "\r\n";
            /* Remark: We don't delete the old pointer here, cause this is done
             * by the caller. We just use the RTString data, which has the
             * scope of this ctor. This is enough cause the data is copied in
             * the DnDHGSendDataMessagePrivate anyway. */
            paParms[3].u.pointer.addr = (void*)strNewUris.c_str();
            paParms[3].u.pointer.size = strNewUris.length() + 1;
            paParms[4].u.uint32       = strNewUris.length() + 1;
        }
    }
    /* Add the size of the data to the todo list. */
    m_cbAll += paParms[4].u.uint32;
    /* The first message is the meta info for the data and the data itself. */
    m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, &DnDHGSendDataMessage::progressCallback, this);

    DO(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));
    DO(("cbAll: %u\n", m_cbAll));
    DO(("cbData: %u\n", paParms[4].u.uint32));

    for (size_t i = 0; i < m_uriList.size(); ++i)
        DO(("file: %s : %s - %o - %ld\n", m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(), m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));
}