STDMETHODIMP CDataObject::SetData(FORMATETC * pFormatEtc, STGMEDIUM * pMedium, BOOL fRelease) { assert(pMedium->tymed != TYMED_NULL); pFormatEtc->tymed = pMedium->tymed; LONG index = LookupFormatEtc(pFormatEtc); if (index == -1) { m_vtFtmEtc.push_back(*pFormatEtc); m_vtStgMedium.push_back(*pMedium); index = m_vtFtmEtc.size() - 1; } else { FORMATETC* lpCurFmtEtc = &m_vtFtmEtc[index]; STGMEDIUM* lpCurStdMedium = &m_vtStgMedium[index]; ::CoTaskMemFree(lpCurFmtEtc->ptd); ::ReleaseStgMedium(lpCurStdMedium); *lpCurFmtEtc = *pFormatEtc; *lpCurStdMedium = *pMedium; } return S_OK; }
// // IDataObject::GetData // HRESULT __stdcall CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { int idx; // // try to match the requested FORMATETC with one of our supported formats // if ((idx = LookupFormatEtc(pFormatEtc)) == -1) { return DV_E_FORMATETC; } // // found a match! transfer the data into the supplied storage-medium // pMedium->tymed = m_pFormatEtc[idx].tymed; pMedium->pUnkForRelease = 0; //pMedium->lpszFileName = switch (m_pFormatEtc[idx].tymed) { case TYMED_HGLOBAL: { pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal); //return S_OK; break; } default: return DV_E_FORMATETC; } return S_OK; }
STDMETHODIMP CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pStgMedium) { LONG idx = LookupFormatEtc(pFormatEtc); if (idx == -1) { return DV_E_FORMATETC; } memset(pStgMedium, 0, sizeof(STGMEDIUM)); if(m_vtFtmEtc[idx].tymed != TYMED_NULL) { if (!CopyStgMedium(pFormatEtc->cfFormat, pStgMedium, &m_vtStgMedium[idx])) { ATLTRACE(L"\nGetData: %d, hr=%x", pFormatEtc->cfFormat, DATA_E_FORMATETC); return DATA_E_FORMATETC; } ATLTRACE(L"\nGetData: %d, hr=%x", pFormatEtc->cfFormat, 0); return S_OK; } ATLTRACE(L"\nGetData: %d, hr=%x", pFormatEtc->cfFormat, DATA_E_FORMATETC); return DATA_E_FORMATETC; }
// // IDataObject::SetData // HRESULT __stdcall CDataObject::SetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease) { int res=LookupFormatEtc(pFormatEtc, pMedium, TRUE); if(-1 == res) { return S_FALSE; } if (m_pStgMedium[res].tymed) { ReleaseStgMedium ( &m_pStgMedium[res] ); ZeroMemory (&m_pStgMedium[res], sizeof(STGMEDIUM) ); } if(fRelease) { m_pStgMedium[res]=*pMedium; } else { CopyStgMedium(pMedium, &m_pStgMedium[res]); } m_pFormatEtc[res].tymed=m_pStgMedium[res].tymed; if(m_pStgMedium[res].tymed==TYMED_HGLOBAL) { m_pStgMedium[res].hGlobal=DupMem(pMedium->hGlobal);//必须分配足够的内存空间和拷贝数据。 } if(GetCanonicalIUnknown(m_pStgMedium[res].pUnkForRelease)== GetCanonicalIUnknown(static_cast<IDataObject*>(this))) { m_pStgMedium[res].pUnkForRelease->Release(); m_pStgMedium[res].pUnkForRelease = NULL; } return S_OK; }
HRESULT __stdcall CDataObject::GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { int idx; if((idx = LookupFormatEtc(pFormatEtc)) == -1) { return DV_E_FORMATETC; } pMedium->tymed = m_pFormatEtc[idx].tymed; pMedium->pUnkForRelease = 0; switch(m_pFormatEtc[idx].tymed) { case TYMED_GDI: pMedium->hBitmap = (HBITMAP)OleDuplicateData(m_pStgMedium[idx].hBitmap, CF_BITMAP, NULL); break; default: return DV_E_FORMATETC; } return S_OK; }
HRESULT CDataObject::GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium) { /* Called by a data consumer to obtain data from a source data object */ if(pFormatEtc == NULL || pMedium == NULL) return E_INVALIDARG; int idx; if((idx = LookupFormatEtc(pFormatEtc)) == -1) return DV_E_FORMATETC; pMedium->tymed = m_pFormatEtc[idx].tymed; pMedium->pUnkForRelease = NULL; switch(m_pFormatEtc[idx].tymed) { case TYMED_HGLOBAL: { pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal); break; } case TYMED_ISTREAM: pMedium->pstm = m_pStgMedium[idx].pstm; pMedium->pstm->AddRef(); break; default: return DV_E_FORMATETC; } return S_OK; }
HRESULT CDataObject::QueryGetData(FORMATETC* pFormatEtc) { /* Determines whether the data object is capable of rendering the data as specified */ return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; }
// // IDataObject::GetData // HRESULT __stdcall CDataObject::GetData (FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { int idx; // // try to match the requested FORMATETC with one of our supported formats // if ((idx = LookupFormatEtc(pFormatEtc)) == -1) { return DV_E_FORMATETC; } // // found a match! transfer the data into the supplied storage-medium // pMedium->tymed = m_pFormatEtc[idx].tymed; pMedium->pUnkForRelease = 0; switch (pMedium->tymed) { case TYMED_HGLOBAL: case TYMED_GDI: case TYMED_ENHMF: // pMedium->hBitmap = (HBITMAP)OleDuplicateData(m_pStgMedium[idx].hBitmap, pFormatEtc->cfFormat, 0); pMedium->hBitmap = m_pStgMedium[idx].hBitmap; break; default: return DV_E_FORMATETC; } if (pMedium->hBitmap == NULL) return STG_E_MEDIUMFULL; return S_OK; }
STDMETHODIMP CDataObject::QueryGetData(FORMATETC *pFormatEtc) { if (LookupFormatEtc(pFormatEtc) >= 0) { return S_OK; } else { return DATA_E_FORMATETC; } }
// // IDataObject::QueryGetData // // Called to see if the IDataObject supports the specified format of data // HRESULT __stdcall CDataObject::QueryGetData(FORMATETC *pFormatEtc) { #ifdef _DEBUG wchar_t szDbg[200]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CDataObject::LookupFormatEtc({cfFormat=x%04X(%u), lindex=%i, tymed=x%02X(%u)})\n", pFormatEtc->cfFormat, pFormatEtc->cfFormat, pFormatEtc->lindex, pFormatEtc->tymed, pFormatEtc->tymed); DEBUGSTRDATA(szDbg); #endif return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; }
HRESULT DataObjectWin::GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium) { int idx; // try to match the specified FORMATETC with one of our supported formats if ((idx = LookupFormatEtc(pFormatEtc)) == -1) return DV_E_FORMATETC; // found a match - transfer data into supplied storage medium pMedium->tymed = m_pFormatEtc[idx].tymed; pMedium->pUnkForRelease = 0; // copy the data into the caller's storage medium switch (m_pFormatEtc[idx].tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = DupGlobalMem(m_pStgMedium[idx].hGlobal); break; default: return DV_E_FORMATETC; } return S_OK; }
// // IDataObject::GetData // HRESULT __stdcall CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium) { int idx; #ifdef _DEBUG wchar_t szDbg[200]; #endif // // try to match the requested FORMATETC with one of our supported formats // if ((idx = LookupFormatEtc(pFormatEtc)) == -1) { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"!!! CDataObject::LookupFormatEtc(%s) failed\n", GetFormatName(pFormatEtc->cfFormat)); DEBUGSTRDATA(szDbg); #endif return DV_E_FORMATETC; } #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CDataObject::GetData {cfFormat=%s, lindex=%i, tymed=x%02X(%u)})", GetFormatName(pFormatEtc->cfFormat), pFormatEtc->lindex, pFormatEtc->tymed, pFormatEtc->tymed); LPCWSTR pszName = GetFormatName(pFormatEtc->cfFormat, true); DWORD nData = (DWORD)-1; if (lstrcmp(pszName, L"IsShowingLayered")==0 || lstrcmp(pszName, L"IsShowingText")==0 || lstrcmp(pszName, L"DragContext")==0 || lstrcmp(pszName, L"UsingDefaultDragImage")==0 || lstrcmp(pszName, L"DragSourceHelperFlags")==0 || lstrcmp(pszName, L"DragWindow")==0 || lstrcmp(pszName, L"DisableDragText")==0 ) { LPDWORD pdw = (LPDWORD)GlobalLock(m_Data[idx].StgMedium.hGlobal); if (pdw) { nData = *pdw; int nLen = lstrlen(szDbg); _wsprintf(szDbg+nLen, SKIPLEN(countof(szDbg)-nLen) L", Data=x%02X(%u)", nData, nData); } GlobalUnlock(m_Data[idx].StgMedium.hGlobal); } wcscat_c(szDbg, L"\n"); DEBUGSTRDATA(szDbg); #endif HRESULT hr = DV_E_FORMATETC; switch (m_Data[idx].FormatEtc.tymed) { case TYMED_HGLOBAL: //ReleaseStgMedium(pMedium); pMedium->hGlobal = DupMem(m_Data[idx].StgMedium.hGlobal); pMedium->pUnkForRelease = NULL; // m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; case TYMED_ISTREAM: _ASSERTE(pMedium->pstm != m_Data[idx].StgMedium.pstm); //ReleaseStgMedium(pMedium); pMedium->pstm = m_Data[idx].StgMedium.pstm; if (m_Data[idx].StgMedium.pstm) m_Data[idx].StgMedium.pstm->AddRef(); pMedium->pUnkForRelease = m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; case TYMED_ISTORAGE: _ASSERTE(pMedium->pstg != m_Data[idx].StgMedium.pstg); //ReleaseStgMedium(pMedium); pMedium->pstg = m_Data[idx].StgMedium.pstg; if (m_Data[idx].StgMedium.pstg) m_Data[idx].StgMedium.pstg->AddRef(); pMedium->pUnkForRelease = m_Data[idx].StgMedium.pUnkForRelease; hr = S_OK; break; default: AssertMsg(L"Unsupported value in m_Data[idx].FormatEtc.tymed"); } if (hr == S_OK) { // // found a match! transfer the data into the supplied storage-medium // pMedium->tymed = m_Data[idx].FormatEtc.tymed; //Assert(pMedium->pUnkForRelease==NULL && m_Data[idx].StgMedium.pUnkForRelease==NULL); //pMedium->pUnkForRelease = NULL; } else { #ifdef _DEBUG _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"!!! CDataObject::GetData(tymed=%u) failed", m_Data[idx].FormatEtc.tymed); DEBUGSTRDATA(szDbg); //_ASSERTE(FALSE && "Unsupported tymed!"); #endif } return hr; }
/** * Retrieves the data stored in this object and store the result in * pMedium. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc * @param pMedium */ STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium) { AssertPtrReturn(pFormatEtc, DV_E_FORMATETC); AssertPtrReturn(pMedium, DV_E_FORMATETC); HRESULT hr = DV_E_FORMATETC; LPFORMATETC pThisFormat = NULL; LPSTGMEDIUM pThisMedium = NULL; LogFlowThisFunc(("\n")); /* Format supported? */ ULONG lIndex; if ( LookupFormatEtc(pFormatEtc, &lIndex) && lIndex < m_cFormats) /* Paranoia. */ { pThisMedium = &m_pStgMedium[lIndex]; AssertPtr(pThisMedium); pThisFormat = &m_pFormatEtc[lIndex]; AssertPtr(pThisFormat); LogFlowThisFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat)); LogFlowThisFunc(("mStatus=%RU32\n", m_enmStatus)); switch (m_enmStatus) { case DnDDataObjectStatus_Dropping: { #if 0 LogRel3(("DnD: Dropping\n")); LogFlowFunc(("Waiting for event ...\n")); int rc2 = RTSemEventWait(m_SemEvent, RT_INDEFINITE_WAIT); LogFlowFunc(("rc=%Rrc, mStatus=%RU32\n", rc2, m_enmStatus)); #endif break; } case DnDDataObjectStatus_Dropped: { LogRel3(("DnD: Dropped\n")); LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), pThisFormat->tymed, pThisFormat->dwAspect)); LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n", m_strFormat.toUtf8().constData(), m_pvData, m_cbData)); QVariant::Type vaType; QString strMIMEType; if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && ( pFormatEtc->cfFormat == CF_TEXT || pFormatEtc->cfFormat == CF_UNICODETEXT) ) { strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */ vaType = QVariant::String; } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_HDROP)) { strMIMEType = "text/uri-list"; vaType = QVariant::StringList; } #if 0 /* More formats; not needed right now. */ else 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; } #endif LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toUtf8().constData(), vaType)); int rc; if (!m_fDataRetrieved) { if (m_pDnDHandler) { rc = m_pDnDHandler->retrieveData(Qt::CopyAction, strMIMEType, vaType, m_vaData); } else rc = VERR_NOT_FOUND; m_fDataRetrieved = true; LogFlowFunc(("Retrieving data ended with %Rrc\n", rc)); } else /* Data already been retrieved. */ rc = VINF_SUCCESS; if ( RT_SUCCESS(rc) && m_vaData.isValid()) { if ( strMIMEType.startsWith("text/uri-list") /* One item. */ && ( m_vaData.canConvert(QVariant::String) /* Multiple items. */ || m_vaData.canConvert(QVariant::StringList)) ) { QStringList lstFilesURI = m_vaData.toStringList(); QStringList lstFiles; for (size_t i = 0; i < lstFilesURI.size(); i++) { char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).toUtf8().constData()); if (pszFilePath) { lstFiles.append(pszFilePath); RTStrFree(pszFilePath); } else /* Unable to parse -- refuse entire request. */ { lstFiles.clear(); rc = VERR_INVALID_PARAMETER; break; } } size_t cFiles = lstFiles.size(); LogFlowThisFunc(("Files (%zu)\n", cFiles)); if ( RT_SUCCESS(rc) && cFiles) { size_t cchFiles = 0; /* Number of characters. */ for (size_t i = 0; i < cFiles; i++) { const char *pszFile = lstFiles.at(i).toUtf8().constData(); cchFiles += strlen(pszFile); cchFiles += 1; /* Terminating '\0'. */ LogFlowThisFunc(("\tFile: %s (cchFiles=%zu)\n", pszFile, cchFiles)); } /* List termination with '\0'. */ cchFiles++; size_t cbBuf = sizeof(DROPFILES) + (cchFiles * sizeof(RTUTF16)); DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf); if (pDropFiles) { /* Put the files list right after our DROPFILES structure. */ pDropFiles->pFiles = sizeof(DROPFILES); /* Offset to file list. */ pDropFiles->fWide = 1; /* We use Unicode. Always. */ uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles; AssertPtr(pCurFile); LogFlowThisFunc(("Encoded:\n")); for (size_t i = 0; i < cFiles; i++) { const char *pszFile = lstFiles.at(i).toUtf8().constData(); Assert(strlen(pszFile)); size_t cchCurFile; PRTUTF16 pwszFile; rc = RTStrToUtf16(pszFile, &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); LogFlowThisFunc(("\t#%zu: cchCurFile=%zu\n", i, cchCurFile)); } if (RT_SUCCESS(rc)) { *pCurFile = L'\0'; /* Final list terminator. */ /* * Fill out the medium structure we're going to report back. */ pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbBuf); if (pMedium->hGlobal) { LPVOID pvMem = GlobalLock(pMedium->hGlobal); if (pvMem) { memcpy(pvMem, pDropFiles, cbBuf); GlobalUnlock(pMedium->hGlobal); hr = S_OK; } else rc = VERR_ACCESS_DENIED; } else rc = VERR_NO_MEMORY; LogFlowThisFunc(("Copying to TYMED_HGLOBAL (%zu bytes): %Rrc\n", cbBuf, rc)); } RTMemFree(pDropFiles); } else rc = VERR_NO_MEMORY; if (RT_FAILURE(rc)) LogFlowThisFunc(("Failed with %Rrc\n", rc)); } } else if ( strMIMEType.startsWith("text/plain") && m_vaData.canConvert(QVariant::String)) { const bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT; const size_t cbCh = fUnicode ? sizeof(WCHAR) : sizeof(char); QString strText = m_vaData.toString(); size_t cbSrc = strText.length() * cbCh; Assert(cbSrc); LPCVOID pvSrc = fUnicode ? (void *)strText.unicode() : (void *)strText.toUtf8().constData(); AssertPtr(pvSrc); LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbCh=%zu, fUnicode=%RTbool\n", pvSrc, cbSrc, cbCh, fUnicode)); pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cbSrc); if (pMedium->hGlobal) { LPVOID pvDst = GlobalLock(pMedium->hGlobal); if (pvDst) { memcpy(pvDst, pvSrc, cbSrc); GlobalUnlock(pMedium->hGlobal); } else rc = VERR_ACCESS_DENIED; hr = S_OK; } else hr = VERR_NO_MEMORY; } else LogRel2(("DnD: MIME type '%s' not supported\n", strMIMEType.toUtf8().constData())); LogFlowThisFunc(("Handling formats ended with rc=%Rrc\n", rc)); } break; } default: break; } } /* * Fallback in error case. */ if (FAILED(hr)) { if (pThisMedium) { switch (pThisMedium->tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, 0 /* Flags */); break; default: break; } } if (pFormatEtc) pMedium->tymed = pFormatEtc->tymed; pMedium->pUnkForRelease = NULL; } LogFlowThisFunc(("Returning hr=%Rhrc\n", hr)); return hr; }
HRESULT __stdcall CDataObject::QueryGetData (FORMATETC *pFormatEtc) { return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; }
/** * Query if this objects supports a specific format. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc */ STDMETHODIMP VBoxDnDDataObject::QueryGetData(FORMATETC *pFormatEtc) { LogFlowFunc(("\n")); return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC; }
/** * 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; }
// // IDataObject::SetData // HRESULT __stdcall CDataObject::SetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium, BOOL fRelease) { _ASSERTE(pMedium && pMedium->pUnkForRelease==NULL); #ifdef _DEBUG LPCWSTR pszName = GetFormatName(pFormatEtc->cfFormat, true); DWORD nData = (DWORD)-1; if (lstrcmp(pszName, L"IsShowingLayered")==0 || lstrcmp(pszName, L"IsShowingText")==0 || lstrcmp(pszName, L"DragContext")==0 || lstrcmp(pszName, L"UsingDefaultDragImage")==0 || lstrcmp(pszName, L"DragSourceHelperFlags")==0 || lstrcmp(pszName, L"DragWindow")==0 || lstrcmp(pszName, L"DisableDragText")==0 ) { LPDWORD pdw = (LPDWORD)GlobalLock(pMedium->hGlobal); if (pdw) { nData = *pdw; } GlobalUnlock(pMedium->hGlobal); } wchar_t szDbg[255]; _wsprintf(szDbg, SKIPLEN(countof(szDbg)) L"CDataObject::SetData {cfFormat=%s, lindex=%i, tymed=x%02X(%u)}, {tymed=x%02X}", GetFormatName(pFormatEtc->cfFormat), pFormatEtc->lindex, pFormatEtc->tymed, pFormatEtc->tymed, pMedium->tymed); if (nData != (DWORD)-1) { int nLen = lstrlen(szDbg); _wsprintf(szDbg+nLen, SKIPLEN(countof(szDbg)-nLen) L", Data=x%02X(%u)", nData, nData); } wcscat_c(szDbg, L"\n"); DEBUGSTRDATA(szDbg); #endif DEBUGTEST(bool bNew = false); LONG nIndex = LookupFormatEtc(pFormatEtc); if (nIndex >= 0) { if ((pMedium != &(m_Data[nIndex].StgMedium)) && (pMedium->hGlobal != &(m_Data[nIndex].StgMedium))) { if (m_Data[nIndex].fRelease) { ReleaseStgMedium(&m_Data[nIndex].StgMedium); } else { ZeroStruct(m_Data[nIndex].StgMedium); } } else { Assert((pMedium != &(m_Data[nIndex].StgMedium)) && (pMedium->hGlobal != &(m_Data[nIndex].StgMedium))); } } else // if (nIndex < 0) { DEBUGTEST(bNew = true); _ASSERTE(nIndex < 0); DragData newItem = {}; newItem.FormatEtc = *pFormatEtc; nIndex = m_Data.push_back(newItem); } m_Data[nIndex].fUsed = TRUE; m_Data[nIndex].fRelease = fRelease; m_Data[nIndex].StgMedium = *pMedium; return S_OK; }
/** * Retrieves the data stored in this object and store the result in * pMedium. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc * @param pMedium */ STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium) { AssertPtrReturn(pFormatEtc, DV_E_FORMATETC); AssertPtrReturn(pMedium, DV_E_FORMATETC); HRESULT hr = DV_E_FORMATETC; LPFORMATETC pThisFormat = NULL; LPSTGMEDIUM pThisMedium = NULL; /* Format supported? */ ULONG lIndex; if ( LookupFormatEtc(pFormatEtc, &lIndex) && lIndex < mcFormats) /* Paranoia. */ { pThisMedium = &mpStgMedium[lIndex]; AssertPtr(pThisMedium); pThisFormat = &mpFormatEtc[lIndex]; AssertPtr(pThisFormat); LogFlowFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat)); LogFlowFunc(("mStatus=%ld\n", mStatus)); switch (mStatus) { case Dropping: { LogRel3(("DnD: Dropping\n")); LogFlowFunc(("Waiting for event ...\n")); int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT); LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus)); } case Dropped: { LogRel3(("DnD: Dropped\n")); LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), pThisFormat->tymed, pThisFormat->dwAspect)); LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n", mstrFormat.toAscii().constData(), mpvData, mcbData)); QVariant::Type vaType; QString strMIMEType; if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && ( pFormatEtc->cfFormat == CF_TEXT || pFormatEtc->cfFormat == CF_UNICODETEXT) ) { strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */ vaType = QVariant::String; } else if ( (pFormatEtc->tymed & TYMED_HGLOBAL) && (pFormatEtc->dwAspect == DVASPECT_CONTENT) && (pFormatEtc->cfFormat == CF_HDROP)) { strMIMEType = "text/uri-list"; vaType = QVariant::StringList; } #if 0 /* More formats; not needed right now. */ else 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; } #endif LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toAscii().constData(), vaType)); int rc; if (!mVaData.isValid()) { /* Note: We're usig Qt::MoveAction because this speeds up the whole operation * significantly: Instead of copying the data from the temporary location to * the final destination we just move it. * * Note2: The Qt::MoveAction *only* affects the behavior on the host! The desired * action for the guest (e.g. moving a file from guest to host) is not affected * by this setting. */ rc = m_pDnDHandler->retrieveData(Qt::MoveAction, strMIMEType, vaType, mVaData); } else rc = VINF_SUCCESS; /* Data already retrieved. */ if (RT_SUCCESS(rc)) { if ( strMIMEType.startsWith("text/uri-list") /* One item. */ && ( mVaData.canConvert(QVariant::String) /* Multiple items. */ || mVaData.canConvert(QVariant::StringList)) ) { QStringList lstFilesURI = mVaData.toStringList(); QStringList lstFiles; for (size_t i = 0; i < lstFilesURI.size(); i++) { /* Extract path from URI. */ char *pszPath = RTUriPath(lstFilesURI.at(i).toAscii().constData()); if ( pszPath && strlen(pszPath) > 1) { pszPath++; /** @todo Skip first '/' (part of URI). Correct? */ pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */); lstFiles.append(pszPath); } } size_t cFiles = lstFiles.size(); Assert(cFiles); #ifdef DEBUG LogFlowFunc(("Files (%zu)\n", cFiles)); for (size_t i = 0; i < cFiles; i++) LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).toAscii().constData())); #endif size_t cchFiles = 0; /* Number of ASCII characters. */ for (size_t i = 0; i < cFiles; i++) { cchFiles += strlen(lstFiles.at(i).toAscii().constData()); cchFiles += 1; /* Terminating '\0'. */ } size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16)); DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf); if (pDropFiles) { pDropFiles->pFiles = sizeof(DROPFILES); pDropFiles->fWide = 1; /* We use unicode. Always. */ uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles; AssertPtr(pCurFile); for (size_t i = 0; i < cFiles; i++) { size_t cchCurFile; PRTUTF16 pwszFile; rc = RTStrToUtf16(lstFiles.at(i).toAscii().constData(), &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 pvMem = GlobalLock(pMedium->hGlobal); if (pvMem) { memcpy(pvMem, pDropFiles, cbBuf); GlobalUnlock(pMedium->hGlobal); hr = S_OK; } else rc = VERR_ACCESS_DENIED; } else rc = VERR_NO_MEMORY; } RTMemFree(pDropFiles); } } else if ( strMIMEType.startsWith("text/plain") && mVaData.canConvert(QVariant::String)) { bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT; int cbCh = fUnicode ? sizeof(WCHAR) : sizeof(char); QString strText = mVaData.toString(); size_t cbSrc = strText.length() * cbCh; Assert(cbSrc); LPCVOID pvSrc = fUnicode ? (void *)strText.unicode() : (void *)strText.toAscii().constData(); AssertPtr(pvSrc); LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbch=%d, fUnicode=%RTbool\n", pvSrc, cbSrc, cbCh, fUnicode)); pMedium->tymed = TYMED_HGLOBAL; pMedium->pUnkForRelease = NULL; pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, cbSrc); if (pMedium->hGlobal) { LPVOID pvDst = GlobalLock(pMedium->hGlobal); if (pvDst) { memcpy(pvDst, pvSrc, cbSrc); GlobalUnlock(pMedium->hGlobal); } else rc = VERR_ACCESS_DENIED; hr = S_OK; } else hr = VERR_NO_MEMORY; } else LogFlowFunc(("MIME type=%s not supported\n", strMIMEType.toAscii().constData())); LogFlowFunc(("Handling formats ended with rc=%Rrc\n", rc)); } } default: break; } } /* * Fallback in error case. */ if (FAILED(hr)) { if (pThisMedium) { switch (pThisMedium->tymed) { case TYMED_HGLOBAL: pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal, pThisFormat->cfFormat, 0 /* Flags */); break; default: break; } } if (pFormatEtc) pMedium->tymed = pFormatEtc->tymed; pMedium->pUnkForRelease = NULL; } LogFlowFunc(("Returning hr=%Rhrc\n", hr)); return hr; }
/** * Query if this objects supports a specific format. * * @return IPRT status code. * @return HRESULT * @param pFormatEtc */ STDMETHODIMP UIDnDDataObject::QueryGetData(LPFORMATETC pFormatEtc) { return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC; }
HRESULT DataObjectWin::QueryGetData(FORMATETC* pFormatEtc) { return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK; }