/* static */ int DnDURIObject::RebaseURIPath(RTCString &strPathAbs, const RTCString &strBaseOld /* = "" */, const RTCString &strBaseNew /* = "" */) { char *pszPath = RTUriFilePath(strPathAbs.c_str()); if (!pszPath) /* No URI? */ pszPath = RTStrDup(strPathAbs.c_str()); int rc; if (pszPath) { const char *pszPathStart = pszPath; const char *pszBaseOld = strBaseOld.c_str(); if ( pszBaseOld && RTPathStartsWith(pszPath, pszBaseOld)) { pszPathStart += strlen(pszBaseOld); } rc = VINF_SUCCESS; if (RT_SUCCESS(rc)) { char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart); if (pszPathNew) { char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */, pszPathNew /* pszPath */, NULL /* pszQuery */, NULL /* pszFragment */); if (pszPathURI) { LogFlowFunc(("Rebasing \"%s\" to \"%s\"\n", strPathAbs.c_str(), pszPathURI)); strPathAbs = RTCString(pszPathURI) + "\r\n"; RTStrFree(pszPathURI); } else rc = VERR_INVALID_PARAMETER; RTStrFree(pszPathNew); } else rc = VERR_NO_MEMORY; } RTStrFree(pszPath); } else rc = VERR_NO_MEMORY; return rc; }
/** @todo Put this into an own class like DnDURIPath : public RTCString? */ int DnDURIObject::RebaseURIPath(RTCString &strPath, const RTCString &strBaseOld, const RTCString &strBaseNew) { int rc; const char *pszPath = RTUriPath(strPath.c_str()); if (pszPath) { const char *pszPathStart = pszPath; const char *pszBaseOld = strBaseOld.c_str(); if ( pszBaseOld && RTPathStartsWith(pszPath, pszBaseOld)) { pszPathStart += strlen(pszBaseOld); } rc = VINF_SUCCESS; if (RT_SUCCESS(rc)) { char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart); if (pszPathNew) { char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */, pszPathNew /* pszPath */, NULL /* pszQuery */, NULL /* pszFragment */); if (pszPathURI) { #ifdef DEBUG_andy LogFlowFunc(("Rebasing \"%s\" to \"%s\"", strPath.c_str(), pszPathURI)); #endif strPath = RTCString(pszPathURI) + "\r\n"; RTStrFree(pszPathURI); rc = VINF_SUCCESS; } else rc = VERR_INVALID_PARAMETER; RTStrFree(pszPathNew); } else rc = VERR_NO_MEMORY; } } else rc = VERR_INVALID_PARAMETER; #ifdef DEBUG_andy LogFlowFuncLeaveRC(rc); #endif return rc; }
RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */, const RTCString &strSeparator /* = "\r\n" */) { RTCString strRet; for (size_t i = 0; i < m_lstRoot.size(); i++) { const char *pszCurRoot = m_lstRoot.at(i).c_str(); #ifdef DEBUG_andy LogFlowFunc(("pszCurRoot=%s\n", pszCurRoot)); #endif if (strBasePath.isNotEmpty()) { char *pszPath = RTPathJoinA(strBasePath.c_str(), pszCurRoot); if (pszPath) { char *pszPathURI = RTUriFileCreate(pszPath); if (pszPathURI) { strRet += RTCString(pszPathURI) + strSeparator; #ifdef DEBUG_andy LogFlowFunc(("URI: %s\n", strRet.c_str())); #endif RTStrFree(pszPathURI); } else break; RTStrFree(pszPath); } else break; } else { char *pszPathURI = RTUriFileCreate(pszCurRoot); if (pszPathURI) { strRet += RTCString(pszPathURI) + strSeparator; #ifdef DEBUG_andy LogFlowFunc(("URI: %s\n", strRet.c_str())); #endif RTStrFree(pszPathURI); } else break; } } return strRet; }
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; }
DnDHGSendDirPrivate(DnDURIObject URIObject, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) : m_URIObject(URIObject) , m_pfnProgressCallback(pfnProgressCallback) , m_pvProgressUser(pvProgressUser) { RTCString strPath = m_URIObject.GetDestPath(); LogFlowFunc(("strPath=%s (%zu)\n", strPath.c_str(), strPath.length())); VBOXHGCMSVCPARM paTmpParms[3]; paTmpParms[0].setString(strPath.c_str()); paTmpParms[1].setUInt32((uint32_t)(strPath.length() + 1)); paTmpParms[2].setUInt32(m_URIObject.GetMode()); m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms); }
/** * Verifies the manifest and its signature. * * @returns VBox status code, failures with message. * @param hManifestFile The xml from the extension pack. * @param pszExtPackName The expected extension pack name. This can be * NULL, in which we don't have any expectations. * @param pszError Where to store an error message on failure. * @param cbError The size of the buffer @a pszError points to. */ static int vboxExtPackVerifyXml(RTVFSFILE hXmlFile, const char *pszExtPackName, char *pszError, size_t cbError) { /* * Load the XML. */ VBOXEXTPACKDESC ExtPackDesc; RTCString *pstrErr = VBoxExtPackLoadDescFromVfsFile(hXmlFile, &ExtPackDesc, NULL); if (pstrErr) { RTStrCopy(pszError, cbError, pstrErr->c_str()); delete pstrErr; return VERR_PARSE_ERROR; } /* * Check the name. */ /** @todo drop this restriction after the old install interface is * dropped. */ int rc = VINF_SUCCESS; if ( pszExtPackName && !ExtPackDesc.strName.equalsIgnoreCase(pszExtPackName)) rc = vboxExtPackReturnError(VERR_NOT_EQUAL, pszError, cbError, "The name of the downloaded file and the name stored inside the extension pack does not match" " (xml='%s' file='%s')", ExtPackDesc.strName.c_str(), pszExtPackName); return rc; }
int CollectorSolaris::getDiskListByFs(const char *name, DiskList& listUsage, DiskList& listLoad) { FsMap::iterator it = mFsMap.find(name); if (it == mFsMap.end()) return VERR_INVALID_PARAMETER; RTCString strName = it->second.substr(0, it->second.find("/")); if (mZpoolOpen && mZpoolClose && mZpoolGetConfig && !strName.isEmpty()) { zpool_handle_t *zh = mZpoolOpen(mZfsLib, strName.c_str()); if (zh) { unsigned int cChildren = 0; nvlist_t **nvChildren = NULL; nvlist_t *nvRoot = NULL; nvlist_t *nvConfig = mZpoolGetConfig(zh, NULL); if ( !nvlist_lookup_nvlist(nvConfig, ZPOOL_CONFIG_VDEV_TREE, &nvRoot) && !nvlist_lookup_nvlist_array(nvRoot, ZPOOL_CONFIG_CHILDREN, &nvChildren, &cChildren)) { for (unsigned int i = 0; i < cChildren; ++i) { uint64_t fHole = 0; uint64_t fLog = 0; nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_HOLE, &fHole); nvlist_lookup_uint64(nvChildren[i], ZPOOL_CONFIG_IS_LOG, &fLog); if (!fHole && !fLog) { char *pszChildName = mZpoolVdevName(mZfsLib, zh, nvChildren[i], _B_FALSE); Assert(pszChildName); RTCString strDevPath("/dev/dsk/"); strDevPath += pszChildName; char szLink[RTPATH_MAX]; if (readlink(strDevPath.c_str(), szLink, sizeof(szLink)) != -1) { char *pszStart, *pszEnd; pszStart = strstr(szLink, "/devices/"); pszEnd = strrchr(szLink, ':'); if (pszStart && pszEnd) { pszStart += 8; // Skip "/devices" *pszEnd = '\0'; // Trim partition listUsage.push_back(physToInstName(pszStart)); } } free(pszChildName); } } } mZpoolClose(zh); } } else listUsage.push_back(pathToInstName(it->second.c_str())); listLoad = listUsage; return VINF_SUCCESS; }
/** * Constructs the extension pack directory path. * * A combination of RTPathJoin and VBoxExtPackMangleName. * * @returns IPRT status code like RTPathJoin. * @param pszExtPackDir Where to return the directory path. * @param cbExtPackDir The size of the return buffer. * @param pszParentDir The parent directory (".../Extensions"). * @param pszName The extension pack name, unmangled. */ int VBoxExtPackCalcDir(char *pszExtPackDir, size_t cbExtPackDir, const char *pszParentDir, const char *pszName) { AssertReturn(VBoxExtPackIsValidName(pszName), VERR_INTERNAL_ERROR_5); RTCString *pstrMangledName = VBoxExtPackMangleName(pszName); if (!pstrMangledName) return VERR_INTERNAL_ERROR_4; int vrc = RTPathJoin(pszExtPackDir, cbExtPackDir, pszParentDir, pstrMangledName->c_str()); delete pstrMangledName; return vrc; }
int DnDHGSendFilePrivate::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextMsg) return VERR_NO_DATA; int rc = m_pNextMsg->getData(uMsg, cParms, paParms); clearNextMsg(); if (RT_FAILURE(rc)) return rc; if (!m_hCurFile) { rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_ALL); if (RT_FAILURE(rc)) return rc; } /* How big is the pointer provided by the guest? */ uint32_t cbToRead = paParms[2].u.pointer.size; size_t cbRead; rc = RTFileRead(m_hCurFile, paParms[2].u.pointer.addr, cbToRead, &cbRead); if (RT_FAILURE(rc)) { /* On error, immediately close the file. */ RTFileClose(m_hCurFile); m_hCurFile = 0; return rc; } m_cbDone += cbRead; /* Tell the guest the actual size. */ paParms[3].setUInt32(cbRead); /* Check if we are done. */ if (m_cbSize == m_cbDone) { RTFileClose(m_hCurFile); m_hCurFile = 0; } else { /* More data! Prepare the next message. */ m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms); } /* Advance progress info */ if ( RT_SUCCESS(rc) && m_pfnProgressCallback) rc = m_pfnProgressCallback(cbRead, m_pvProgressUser); return rc; }
int DnDURIList::AppendURIPathsFromList(const RTCList<RTCString> &lstURI, uint32_t fFlags) { int rc = VINF_SUCCESS; for (size_t i = 0; i < lstURI.size(); i++) { RTCString strURI = lstURI.at(i); rc = AppendURIPath(strURI.c_str(), fFlags); if (RT_FAILURE(rc)) break; } LogFlowFuncLeaveRC(rc); return rc; }
/** * Parse the given buffer and fills the given Document object with its contents. * Throws XmlError on parsing errors. * * The document that is passed in will be reset before being filled if not empty. * * @param pvBuf in: memory buffer to parse. * @param cbSize in: size of the memory buffer. * @param strFilename in: name fo file to parse. * @param doc out: document to be reset and filled with data according to file contents. */ void XmlMemParser::read(const void* pvBuf, size_t cbSize, const RTCString &strFilename, Document &doc) { GlobalLock lock; // global.setExternalEntityLoader(ExternalEntityLoader); const char *pcszFilename = strFilename.c_str(); doc.m->reset(); if (!(doc.m->plibDocument = xmlCtxtReadMemory(m_ctxt, (const char*)pvBuf, (int)cbSize, pcszFilename, NULL, // encoding = auto XML_PARSE_NOBLANKS | XML_PARSE_NONET))) throw XmlError(xmlCtxtGetLastError(m_ctxt)); doc.refreshInternals(); }
bool Filter::match(const ComPtr<IUnknown> object, const RTCString &name) const { ElementList::const_iterator it; //LogAleksey(("Filter::match(%p, %s)\n", static_cast<const IUnknown*> (object), name.c_str())); for (it = mElements.begin(); it != mElements.end(); it++) { //LogAleksey(("...matching against(%p, %s)\n", static_cast<const IUnknown*> ((*it).first), (*it).second.c_str())); if ((*it).first.isNull() || (*it).first == object) { // Objects match, compare names if (patternMatch((*it).second.c_str(), name.c_str())) { LogFlowThisFunc(("...found!\n")); return true; } } } //LogAleksey(("...no matches!\n")); return false; }
/** * Reads the given file and fills the given Document object with its contents. * Throws XmlError on parsing errors. * * The document that is passed in will be reset before being filled if not empty. * * @param strFilename in: name fo file to parse. * @param doc out: document to be reset and filled with data according to file contents. */ void XmlFileParser::read(const RTCString &strFilename, Document &doc) { GlobalLock lock; // global.setExternalEntityLoader(ExternalEntityLoader); m->strXmlFilename = strFilename; const char *pcszFilename = strFilename.c_str(); ReadContext context(pcszFilename); doc.m->reset(); if (!(doc.m->plibDocument = xmlCtxtReadIO(m_ctxt, ReadCallback, CloseCallback, &context, pcszFilename, NULL, // encoding = auto XML_PARSE_NOBLANKS | XML_PARSE_NONET))) throw XmlError(xmlCtxtGetLastError(m_ctxt)); doc.refreshInternals(); }
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; }
/** * Open the object with a specific file type, and, depending on the type, specifying additional parameters. * * @return IPRT status code. * @param strPathAbs Absolute path of the object (file / directory / ...). * @param enmView View of the object. * @param fOpen Open mode to use; only valid for file objects. * @param fMode File mode to use; only valid for file objects. * @param fFlags Additional DnD URI object flags. */ int DnDURIObject::OpenEx(const RTCString &strPathAbs, View enmView, uint64_t fOpen /* = 0 */, RTFMODE fMode /* = 0 */, DNDURIOBJECTFLAGS fFlags /* = DNDURIOBJECT_FLAGS_NONE */) { AssertReturn(!(fFlags & ~DNDURIOBJECT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS); RT_NOREF1(fFlags); int rc = VINF_SUCCESS; switch (enmView) { case View_Source: m_strSrcPathAbs = strPathAbs; break; case View_Target: m_strTgtPathAbs = strPathAbs; break; default: rc = VERR_NOT_IMPLEMENTED; break; } if ( RT_SUCCESS(rc) && fOpen) /* Opening mode specified? */ { LogFlowThisFunc(("strPath=%s, enmView=%RU32, fOpen=0x%x, fMode=0x%x, fFlags=0x%x\n", strPathAbs.c_str(), enmView, fOpen, fMode, fFlags)); switch (m_enmType) { case Type_File: { /* * Open files on the source with RTFILE_O_DENY_WRITE to prevent races * where the OS writes to the file while the destination side transfers * it over. */ LogFlowThisFunc(("Opening ...\n")); rc = RTFileOpen(&u.File.hFile, strPathAbs.c_str(), fOpen); if (RT_SUCCESS(rc)) { if ( (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */ && fMode /* Some file mode to set specified? */) { rc = RTFileSetMode(u.File.hFile, fMode); } else if (fOpen & RTFILE_O_READ) { rc = queryInfoInternal(enmView); } } if (RT_SUCCESS(rc)) { LogFlowThisFunc(("File cbObject=%RU64, fMode=0x%x\n", u.File.objInfo.cbObject, u.File.objInfo.Attr.fMode)); u.File.cbToProcess = u.File.objInfo.cbObject; u.File.cbProcessed = 0; } break; } case Type_Directory: { rc = RTDirOpen(&u.Dir.hDir, strPathAbs.c_str()); if (RT_SUCCESS(rc)) rc = queryInfoInternal(enmView); break; } default: rc = VERR_NOT_IMPLEMENTED; break; } } if (RT_SUCCESS(rc)) { m_enmView = enmView; } LogFlowFuncLeaveRC(rc); return rc; }
/* * 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)); }
STDMETHODIMP VBoxDnDDropTarget::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { RT_NOREF(pt); AssertPtrReturn(pDataObject, E_INVALIDARG); AssertPtrReturn(pdwEffect, E_INVALIDARG); LogFlowFunc(("mFormatEtc.cfFormat=%RI16 (%s), pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), pDataObject, grfKeyState, pt.x, pt.y)); HRESULT hr = S_OK; if (mFormatEtc.cfFormat) /* Did we get a supported format yet? */ { /* Make sure the data object's data format is still valid. */ hr = pDataObject->QueryGetData(&mFormatEtc); AssertMsg(SUCCEEDED(hr), ("Data format changed to invalid between DragEnter() and Drop(), cfFormat=%RI16 (%s), hr=%Rhrc\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), hr)); } int rc = VINF_SUCCESS; if (SUCCEEDED(hr)) { STGMEDIUM stgMed; hr = pDataObject->GetData(&mFormatEtc, &stgMed); if (SUCCEEDED(hr)) { /* * First stage: Prepare the access to the storage medium. * For now we only support HGLOBAL stuff. */ PVOID pvData = NULL; /** @todo Put this in an own union? */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: pvData = GlobalLock(stgMed.hGlobal); if (!pvData) { LogFlowFunc(("Locking HGLOBAL storage failed with %Rrc\n", RTErrConvertFromWin32(GetLastError()))); rc = VERR_INVALID_HANDLE; hr = E_INVALIDARG; /* Set special hr for OLE. */ } break; default: AssertMsgFailed(("Storage medium type %RI32 supported\n", mFormatEtc.tymed)); rc = VERR_NOT_SUPPORTED; hr = DV_E_TYMED; /* Set special hr for OLE. */ break; } if (RT_SUCCESS(rc)) { /* * Second stage: Do the actual copying of the data object's data, * based on the storage medium type. */ switch (mFormatEtc.cfFormat) { case CF_TEXT: /* Fall through is intentional. */ case CF_UNICODETEXT: { AssertPtr(pvData); size_t cbSize = GlobalSize(pvData); LogFlowFunc(("CF_TEXT/CF_UNICODETEXT 0x%p got %zu bytes\n", pvData, cbSize)); if (cbSize) { char *pszText = NULL; rc = mFormatEtc.cfFormat == CF_TEXT /* ANSI codepage -> UTF-8 */ ? RTStrCurrentCPToUtf8(&pszText, (char *)pvData) /* Unicode -> UTF-8 */ : RTUtf16ToUtf8((PCRTUTF16)pvData, &pszText); if (RT_SUCCESS(rc)) { AssertPtr(pszText); size_t cbText = strlen(pszText) + 1; /* Include termination. */ mpvData = RTMemDup((void *)pszText, cbText); mcbData = cbText; RTStrFree(pszText); pszText = NULL; } } break; } case CF_HDROP: { AssertPtr(pvData); /* Convert to a string list, separated by \r\n. */ DROPFILES *pDropFiles = (DROPFILES *)pvData; AssertPtr(pDropFiles); bool fUnicode = RT_BOOL(pDropFiles->fWide); /* Get the offset of the file list. */ Assert(pDropFiles->pFiles >= sizeof(DROPFILES)); /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only * will work with the plain storage medium pointer! */ HDROP hDrop = (HDROP)(pvData); /* First, get the file count. */ /** @todo Does this work on Windows 2000 / NT4? */ char *pszFiles = NULL; uint32_t cchFiles = 0; UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */); LogFlowFunc(("CF_HDROP got %RU16 file(s)\n", cFiles)); for (UINT i = 0; i < cFiles; i++) { UINT cch = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */); Assert(cch); if (RT_FAILURE(rc)) break; char *pszFile = NULL; /* UTF-8 version. */ UINT cchFile = 0; if (fUnicode) { /* Allocate enough space (including terminator). */ WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cch + 1) * sizeof(WCHAR)); if (pwszFile) { cchFile = DragQueryFileW(hDrop, i /* File index */, pwszFile, cch + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); rc = RTUtf16ToUtf8(pwszFile, &pszFile); AssertRC(rc); RTMemFree(pwszFile); } else rc = VERR_NO_MEMORY; } else /* ANSI */ { /* Allocate enough space (including terminator). */ pszFile = (char *)RTMemAlloc((cch + 1) * sizeof(char)); if (pszFile) { cchFile = DragQueryFileA(hDrop, i /* File index */, pszFile, cchFile + 1 /* Include terminator */); AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n", cchFile, cch)); } else rc = VERR_NO_MEMORY; } if (RT_SUCCESS(rc)) { LogFlowFunc(("\tFile: %s (cchFile=%RU32)\n", pszFile, cchFile)); rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFile, cchFile); if (RT_SUCCESS(rc)) cchFiles += cchFile; } if (pszFile) RTStrFree(pszFile); if (RT_FAILURE(rc)) break; /* Add separation between filenames. * Note: Also do this for the last element of the list. */ rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */); if (RT_SUCCESS(rc)) cchFiles += 2; /* Include \r\n */ } if (RT_SUCCESS(rc)) { cchFiles += 1; /* Add string termination. */ uint32_t cbFiles = cchFiles * sizeof(char); LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n", cFiles, cchFiles, cbFiles, pszFiles)); /* Translate the list into URI elements. */ DnDURIList lstURI; rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles, DNDURILIST_FLAGS_ABSOLUTE_PATHS); if (RT_SUCCESS(rc)) { RTCString strRoot = lstURI.RootToString(); size_t cbRoot = strRoot.length() + 1; /* Include termination */ mpvData = RTMemAlloc(cbRoot); if (mpvData) { memcpy(mpvData, strRoot.c_str(), cbRoot); mcbData = cbRoot; } else rc = VERR_NO_MEMORY; } } LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n", rc, pszFiles, cFiles, cchFiles)); if (pszFiles) RTStrFree(pszFiles); break; } default: /* Note: Should not happen due to the checks done in DragEnter(). */ AssertMsgFailed(("Format of type %RI16 (%s) not supported\n", mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat))); hr = DV_E_CLIPFORMAT; /* Set special hr for OLE. */ break; } /* * Third stage: Unlock + release access to the storage medium again. */ switch (mFormatEtc.tymed) { case TYMED_HGLOBAL: GlobalUnlock(stgMed.hGlobal); break; default: AssertMsgFailed(("Really should not happen -- see init stage!\n")); break; } } /* Release storage medium again. */ ReleaseStgMedium(&stgMed); /* Signal waiters. */ mDroppedRc = rc; RTSemEventSignal(hEventDrop); } } if (RT_SUCCESS(rc)) { /* Note: pt is not used since we don't need to differentiate within our * proxy window. */ *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect); } else *pdwEffect = DROPEFFECT_NONE; if (mpWndParent) mpWndParent->hide(); LogFlowFunc(("Returning with hr=%Rhrc (%Rrc), mFormatEtc.cfFormat=%RI16 (%s), *pdwEffect=%RI32\n", hr, rc, mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat), *pdwEffect)); return hr; }
/* * 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); }
int DnDURIObject::OpenEx(const RTCString &strPath, Type enmType, Dest enmDest, uint64_t fOpen /* = 0 */, uint32_t fMode /* = 0 */, uint32_t fFlags /* = 0 */) { int rc = VINF_SUCCESS; switch (enmDest) { case Source: m_strSrcPath = strPath; break; case Target: m_strTgtPath = strPath; break; default: rc = VERR_NOT_IMPLEMENTED; break; } if ( RT_SUCCESS(rc) && fOpen) /* Opening mode specified? */ { switch (enmType) { case File: { if (!u.m_hFile) { /* * Open files on the source with RTFILE_O_DENY_WRITE to prevent races * where the OS writes to the file while the destination side transfers * it over. */ rc = RTFileOpen(&u.m_hFile, strPath.c_str(), fOpen); LogFlowThisFunc(("strPath=%s, fOpen=0x%x, enmType=%RU32, enmDest=%RU32, rc=%Rrc\n", strPath.c_str(), fOpen, enmType, enmDest, rc)); if (RT_SUCCESS(rc)) rc = RTFileGetSize(u.m_hFile, &m_cbSize); if (RT_SUCCESS(rc)) { if ( (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */ && fMode /* Some file mode to set specified? */) { rc = RTFileSetMode(u.m_hFile, fMode); if (RT_SUCCESS(rc)) m_fMode = fMode; } else if (fOpen & RTFILE_O_READ) { #if 0 /** @todo Enable this as soon as RTFileGetMode is implemented. */ rc = RTFileGetMode(u.m_hFile, &m_fMode); #else RTFSOBJINFO ObjInfo; rc = RTFileQueryInfo(u.m_hFile, &ObjInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) m_fMode = ObjInfo.Attr.fMode; #endif } } if (RT_SUCCESS(rc)) { LogFlowThisFunc(("cbSize=%RU64, fMode=0x%x\n", m_cbSize, m_fMode)); m_cbProcessed = 0; } } else rc = VINF_SUCCESS; break; } case Directory: rc = VINF_SUCCESS; break; default: rc = VERR_NOT_IMPLEMENTED; break; } } if (RT_SUCCESS(rc)) m_Type = enmType; LogFlowFuncLeaveRC(rc); return rc; }