/* static */ void VBoxDnDDropTarget::DumpFormats(IDataObject *pDataObject) { AssertPtrReturnVoid(pDataObject); /* Enumerate supported source formats. This shouldn't happen too often * on day to day use, but still keep it in here. */ IEnumFORMATETC *pEnumFormats; HRESULT hr2 = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormats); if (SUCCEEDED(hr2)) { LogRel(("DnD: The following formats were offered to us:\n")); FORMATETC curFormatEtc; while (pEnumFormats->Next(1, &curFormatEtc, NULL /* pceltFetched */) == S_OK) { WCHAR wszCfName[128]; /* 128 chars should be enough, rest will be truncated. */ hr2 = GetClipboardFormatNameW(curFormatEtc.cfFormat, wszCfName, sizeof(wszCfName) / sizeof(WCHAR)); LogRel(("\tcfFormat=%RI16 (%s), tyMed=%RI32, dwAspect=%RI32, strCustomName=%ls, hr=%Rhrc\n", curFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(curFormatEtc.cfFormat), curFormatEtc.tymed, curFormatEtc.dwAspect, wszCfName, hr2)); } pEnumFormats->Release(); } }
HRESULT CProjectHierarchyWnd::LocalDragEnter(IDataObject *pDataObj, DWORD /*grfKeyState*/, POINTL /*pt*/, DWORD *pdwEffect) { IEnumFORMATETC *pFormatEnum; m_bAcceptDrag = false; *pdwEffect = DROPEFFECT_NONE; if(pDataObj->EnumFormatEtc(DATADIR_GET, &pFormatEnum) == S_OK) { FORMATETC formatetc; while(pFormatEnum->Next(1, &formatetc, NULL) == S_OK) { if(formatetc.cfFormat == loadngo::data::TaskDataObject::CF_TASK_ID || formatetc.cfFormat == loadngo::data::CUserItemData::CF_USERITEM_ID || formatetc.cfFormat == loadngo::data::AnnotationDataObject::CF_ANNOTATION_ID /*formatetc.cfFormat == CF_TEXT || formatetc.cfFormat == CF_UNICODETEXT || formatetc.cfFormat == CF_OEMTEXT || formatetc.cfFormat == CF_HDROP*/) { *pdwEffect = DROPEFFECT_COPY; m_bAcceptDrag = true; break; } } } pFormatEnum->Release(); return S_OK; }
// Name : wxIDropTarget::DragEnter // Purpose : Called when the mouse enters the window (dragging something) // Returns : S_OK // Params : [in] IDataObject *pIDataSource : source data // [in] DWORD grfKeyState : kbd & mouse state // [in] POINTL pt : mouse coordinates // [in/out]DWORD *pdwEffect : effect flag // In: Supported effects // Out: Resulting effect // Notes : STDMETHODIMP wxIDropTarget::DragEnter(IDataObject *pIDataSource, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { wxLogTrace(wxTRACE_OleCalls, wxT("IDropTarget::DragEnter")); wxASSERT_MSG( m_pIDataObject == NULL, wxT("drop target must have data object") ); // show the list of formats supported by the source data object for the // debugging purposes, this is quite useful sometimes - please don't remove #if 0 IEnumFORMATETC *penumFmt; if ( SUCCEEDED(pIDataSource->EnumFormatEtc(DATADIR_GET, &penumFmt)) ) { FORMATETC fmt; while ( penumFmt->Next(1, &fmt, NULL) == S_OK ) { wxLogDebug(wxT("Drop source supports format %s"), wxDataObject::GetFormatName(fmt.cfFormat)); } penumFmt->Release(); } else { wxLogLastError(wxT("IDataObject::EnumFormatEtc")); } #endif // 0 if ( !m_pTarget->MSWIsAcceptedData(pIDataSource) ) { // we don't accept this kind of data *pdwEffect = DROPEFFECT_NONE; return S_OK; } // for use in OnEnter and OnDrag calls m_pTarget->MSWSetDataSource(pIDataSource); // get hold of the data object m_pIDataObject = pIDataSource; m_pIDataObject->AddRef(); // we need client coordinates to pass to wxWin functions if ( !ScreenToClient(m_hwnd, (POINT *)&pt) ) { wxLogLastError(wxT("ScreenToClient")); } // give some visual feedback *pdwEffect = ConvertDragResultToEffect( m_pTarget->OnEnter(pt.x, pt.y, ConvertDragEffectToResult( GetDropEffect(grfKeyState, m_pTarget->GetDefaultAction(), *pdwEffect)) ) ); return S_OK; }
// Registers a DataFlavor/FE pair void nsDataObjCollection::AddDataFlavor(const char * aDataFlavor, LPFORMATETC aFE) { // Add the FormatEtc to our list if it's not already there. We don't care // about the internal aDataFlavor because nsDataObj handles that. IEnumFORMATETC * ifEtc; FORMATETC fEtc; ULONG num; if (S_OK != this->EnumFormatEtc(DATADIR_GET, &ifEtc)) return; while (S_OK == ifEtc->Next(1, &fEtc, &num)) { NS_ASSERTION(1 == num, "Bit off more than we can chew in nsDataObjCollection::AddDataFlavor"); if (FormatsMatch(fEtc, *aFE)) { ifEtc->Release(); return; } } // If we didn't find a matching format, add this one ifEtc->Release(); m_enumFE->AddFormatEtc(aFE); }
static void sFilterNonHGLOBAL(IDataObject* iDataObject, vector<FORMATETC>& oVector) { IEnumFORMATETC* theEnum; if (SUCCEEDED(iDataObject->EnumFormatEtc(DATADIR_GET, &theEnum))) { FORMATETC theFORMATETC; ULONG returnedCount; while (SUCCEEDED(theEnum->Next(1, &theFORMATETC, &returnedCount)) && returnedCount != 0) { if (theFORMATETC.tymed & TYMED_HGLOBAL) oVector.push_back(theFORMATETC); } theEnum->Release(); } }
STDMETHODIMP UDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) { GuiLock __; LLOG("DragEnter " << pt); data = pDataObj; data->AddRef(); fmt.Clear(); IEnumFORMATETC *fe; if(!ctrl || pDataObj->EnumFormatEtc(DATADIR_GET, &fe) != NOERROR) { *pdwEffect = DROPEFFECT_NONE; return NOERROR; } FORMATETC fmtetc; while(fe->Next(1, &fmtetc, 0) == S_OK) { fmt.FindAdd(FromWin32CF(fmtetc.cfFormat)); if(fmtetc.ptd) CoTaskMemFree(fmtetc.ptd); } fe->Release(); DnD(pt, false, pdwEffect, grfKeyState); return NOERROR; }
bool wxClipboard::GetData( wxDataObject& data ) { #if wxUSE_OLE_CLIPBOARD IDataObject *pDataObject = NULL; HRESULT hr = OleGetClipboard(&pDataObject); if ( FAILED(hr) || !pDataObject ) { wxLogSysError(hr, _("Failed to get data from the clipboard")); return false; } // build the list of supported formats size_t nFormats = data.GetFormatCount(wxDataObject::Set); wxDataFormat format; wxDataFormat *formats; if ( nFormats == 1 ) { // the most common case formats = &format; } else { // bad luck, need to alloc mem formats = new wxDataFormat[nFormats]; } data.GetAllFormats(formats, wxDataObject::Set); // get the data for the given formats FORMATETC formatEtc; CLIPFORMAT cf; bool result = false; // enumerate all explicit formats on the clipboard. // note that this does not include implicit / synthetic (automatically // converted) formats. #ifdef __WXDEBUG__ // get the format enumerator IEnumFORMATETC *pEnumFormatEtc = NULL; hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormatEtc); if ( FAILED(hr) || !pEnumFormatEtc ) { wxLogSysError(hr, _("Failed to retrieve the supported clipboard formats")); } else { // ask for the supported formats and see if there are any we support for ( ;; ) { ULONG nCount; hr = pEnumFormatEtc->Next(1, &formatEtc, &nCount); // don't use FAILED() because S_FALSE would pass it if ( hr != S_OK ) { // no more formats break; } cf = formatEtc.cfFormat; wxLogTrace(wxTRACE_OleCalls, wxT("Object on the clipboard supports format %s."), wxDataObject::GetFormatName(cf)); } pEnumFormatEtc->Release(); } #endif // Debug STGMEDIUM medium; // stop at the first valid format found on the clipboard for ( size_t n = 0; !result && (n < nFormats); n++ ) { // convert to NativeFormat Id cf = formats[n].GetFormatId(); // if the format is not available, try the next one // this test includes implicit / sythetic formats if ( !::IsClipboardFormatAvailable(cf) ) continue; formatEtc.cfFormat = cf; formatEtc.ptd = NULL; formatEtc.dwAspect = DVASPECT_CONTENT; formatEtc.lindex = -1; // use the appropriate tymed switch ( formatEtc.cfFormat ) { case CF_BITMAP: formatEtc.tymed = TYMED_GDI; break; #ifndef __WXWINCE__ case CF_METAFILEPICT: formatEtc.tymed = TYMED_MFPICT; break; case CF_ENHMETAFILE: formatEtc.tymed = TYMED_ENHMF; break; #endif default: formatEtc.tymed = TYMED_HGLOBAL; } // try to get data hr = pDataObject->GetData(&formatEtc, &medium); if ( FAILED(hr) ) { // try other tymed for GDI objects if ( formatEtc.cfFormat == CF_BITMAP ) { formatEtc.tymed = TYMED_HGLOBAL; hr = pDataObject->GetData(&formatEtc, &medium); } } if ( SUCCEEDED(hr) ) { // pass the data to the data object hr = data.GetInterface()->SetData(&formatEtc, &medium, true); if ( FAILED(hr) ) { wxLogDebug(wxT("Failed to set data in wxIDataObject")); // IDataObject only takes the ownership of data if it // successfully got it - which is not the case here ReleaseStgMedium(&medium); } else { result = true; } } //else: unsupported tymed? } if ( formats != &format ) { delete [] formats; } //else: we didn't allocate any memory // clean up and return pDataObject->Release(); return result; #elif wxUSE_DATAOBJ wxCHECK_MSG( wxIsClipboardOpened(), false, wxT("clipboard not open") ); wxDataFormat format = data.GetPreferredFormat(); switch ( format ) { case wxDF_TEXT: case wxDF_OEMTEXT: { wxTextDataObject& textDataObject = (wxTextDataObject &)data; char* s = (char*)wxGetClipboardData(format); if ( !s ) return false; textDataObject.SetText(wxString::FromAscii(s)); delete [] s; return true; } case wxDF_BITMAP: case wxDF_DIB: { wxBitmapDataObject& bitmapDataObject = (wxBitmapDataObject &)data; wxBitmap* bitmap = (wxBitmap *)wxGetClipboardData(data.GetPreferredFormat()); if ( !bitmap ) return false; bitmapDataObject.SetBitmap(*bitmap); delete bitmap; return true; } #if wxUSE_METAFILE case wxDF_METAFILE: { wxMetafileDataObject& metaFileDataObject = (wxMetafileDataObject &)data; wxMetafile* metaFile = (wxMetafile *)wxGetClipboardData(wxDF_METAFILE); if ( !metaFile ) return false; metaFileDataObject.SetMetafile(*metaFile); delete metaFile; return true; } #endif // wxUSE_METAFILE } return false; #else // !wxUSE_DATAOBJ wxFAIL_MSG( wxT("no clipboard implementation") ); return false; #endif // wxUSE_OLE_CLIPBOARD/wxUSE_DATAOBJ }
STDMETHODIMP CDDShellExt::Initialize(LPCITEMIDLIST pidlFolder,LPDATAOBJECT pDO,HKEY hProgID) { (void)hProgID; if(!connected) { bool b = m_ac.connectToServer(); if (b==true) { connected=true; } else return E_FAIL; } FORMATETC fmt={CF_HDROP,NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL}; STGMEDIUM stg={TYMED_HGLOBAL}; HDROP hDrop; fDestDir[0]=0; if (!SHGetPathFromIDList(pidlFolder,fDestDir)) { #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG MessageBox(NULL,L"Initialize",L"E_FAIL 1",MB_OK); #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG return E_FAIL; } // Detect if it's explorer that started the operation by enumerating available // clipboard formats and searching for one that only explorer uses IEnumFORMATETC *en; FORMATETC fmt2; WCHAR fmtName[256]=L"\0"; fFromExplorer=false; pDO->EnumFormatEtc(DATADIR_GET,&en); while(en->Next(1,&fmt2,NULL)==S_OK){ GetClipboardFormatName(fmt2.cfFormat,fmtName,256); if (!wcscmp(fmtName,CFSTR_SHELLIDLIST)) fFromExplorer=true; } en->Release(); // Look for CF_HDROP data in the data object. If there // is no such data, return an error back to Explorer. if (FAILED(pDO->GetData(&fmt,&stg))) { #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG MessageBox(NULL,L"Initialize",L"E_INVALIDARG 2",MB_OK); #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG return E_INVALIDARG; } // Get a pointer to the actual data. hDrop=(HDROP)GlobalLock(stg.hGlobal); // Make sure it worked. if (hDrop==NULL) { #ifdef CATCHCOPY_EXPLORER_PLUGIN_DEBUG MessageBox(NULL,L"Initialize",L"E_INVALIDARG 1",MB_OK); #endif // CATCHCOPY_EXPLORER_PLUGIN_DEBUG return E_INVALIDARG; } UINT numFiles,i; WCHAR fn[MAX_PATH]=L""; numFiles=DragQueryFile(hDrop,0xFFFFFFFF,NULL,0); if (numFiles) { for(i=0;i<numFiles;++i) { if(DragQueryFile(hDrop,i,fn,MAX_PATH)) sources.push_back(fn); } } GlobalUnlock(stg.hGlobal); ReleaseStgMedium(&stg); return S_OK; }
STDMETHODIMP CDropTarget::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { #ifdef _DEBUG printf("IDropTarget::Drop\n"); #endif //_DEBUG DWORD dwOKEffects = *pdwEffect; { //We do this because grfKeyState will always have the mouse button used off DWORD temp = LastKeyState; //Get the position of the drop DragOver(grfKeyState, pt, pdwEffect); LastKeyState = temp; } //Remove the effects pDataObj = NULL; DragLeave(); bool copying = (*pdwEffect & DROPEFFECT_COPY) != 0; size_t totallen = 0; BYTE *data = NULL; bool gotdata = false; UINT *formats = NULL; UINT numformats = 0; FORMATETC *fel = NULL; UINT numfe = 0; bool NeedToChooseFormat = true; int IndexOfDataToInsert = -1; bool NeedToChooseMoveorCopy = (LastKeyState | grfKeyState) & (MK_MBUTTON | MK_RBUTTON) || hexwnd.always_pick_move_copy; if (hexwnd.dragging) // Internal data { hexwnd.dragging = FALSE; if (NeedToChooseMoveorCopy) { int choice = PopupDropMenu(pt); if (choice == 0) { pDataObject->Release(); *pdwEffect = DROPEFFECT_NONE; return S_OK; } copying = choice != 1; } int iMove1stEnd = hexwnd.iGetStartOfSelection(); int iMove2ndEndorLen = hexwnd.iGetEndOfSelection(); int iMovePosOrg = hexwnd.new_pos; if (!copying && hexwnd.new_pos > iMove2ndEndorLen) hexwnd.new_pos += iMove1stEnd - iMove2ndEndorLen - 1; iMovePos = hexwnd.new_pos; iMoveOpTyp = copying ? OPTYP_COPY : OPTYP_MOVE; SimpleArray<BYTE> olddata; const int len = iMove2ndEndorLen - iMove1stEnd + 1; if (grfKeyState & MK_SHIFT) // Overwrite { if (copying) { //Just [realloc &] memmove if (iMovePos + len > hexwnd.m_dataArray.GetLength()) // Need more space { olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], hexwnd.m_dataArray.GetLength() - iMovePos); if (hexwnd.m_dataArray.SetSize(iMovePos + len)) { hexwnd.m_dataArray.ExpandToSize(); memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len); } } else // Enough space { olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], len); memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len); } hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], len); } else //Moving { if (iMovePos > iMove1stEnd) //Forward { olddata.AppendArray(&hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg + len - iMove1stEnd); hexwnd.move_copy_sub(iMove1stEnd, iMove2ndEndorLen, 0); hexwnd.m_dataArray.RemoveAt(iMovePos+len,len); hexwnd.push_undorecord(iMove1stEnd, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg - iMove1stEnd); } else //Backward { if (iMove1stEnd-iMovePos>=len) { olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - iMovePos); memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len); hexwnd.m_dataArray.RemoveAt(iMove1stEnd,len); } else { olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - (iMovePos + len - iMove1stEnd) - iMovePos); memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len); hexwnd.m_dataArray.RemoveAt(iMovePos+len,len-(iMovePos + len - iMove1stEnd)); } hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], iMove1stEnd - iMovePos); } } hexwnd.iStartOfSelection = iMovePos; hexwnd.iEndOfSelection = iMovePos+len-1; hexwnd.bFilestatusChanged = true; hexwnd.bSelected = true; hexwnd.resize_window(); } else // Insert { hexwnd.CMD_move_copy(iMove1stEnd, iMove2ndEndorLen, 1); } } else // External data { STGMEDIUM stm; HRESULT err = E_UNEXPECTED; //Get the formats enumerator IEnumFORMATETC *iefe = 0; pDataObject->EnumFormatEtc(DATADIR_GET, &iefe); if (iefe == 0) { #ifdef _DEBUG printf("Unable to create a drag-drop data enumerator\n"); #endif //_DEBUG goto ERR; } iefe->Reset(); //Get the available formats for(;;) { void *temp = realloc(fel, (numfe + 1) * sizeof(FORMATETC)); if (temp != NULL) { fel = (FORMATETC*) temp; temp = NULL; int r; r = iefe->Next(1, &fel[numfe], NULL); if (r != S_OK) break;//No more formats numfe++; } else if (fel == NULL) { //We only go here if nothing could be allocated #ifdef _DEBUG printf("Not enough memory for the drag-drop format list\n"); #endif //_DEBUG goto ERR_ENUM; } } UINT i; /*Check which format should be inserted according to user preferences*/ if (numfe == 0) { MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_NO_DATA), MB_OK); err = S_OK; *pdwEffect = DROPEFFECT_NONE; goto ERR_ENUM; } if (hexwnd.prefer_CF_HDROP) { for (i = 0 ; i < numfe ; i++) { if (fel[i].cfFormat == CF_HDROP) { //Return no effect & let shell32 handle it if (S_OK == pDataObject->GetData(&fel[i], &stm)) { hexwnd.dropfiles((HDROP)stm.hGlobal); } err = S_OK; *pdwEffect = DROPEFFECT_NONE; goto ERR_ENUM; } } } if (numfe == 1) { IndexOfDataToInsert = 0; } else if (hexwnd.prefer_CF_BINARYDATA) { for (i = 0 ; i < numfe ; i++) { if (fel[i].cfFormat == CF_BINARYDATA) { NeedToChooseFormat = false; IndexOfDataToInsert = i; break; } } } else if (hexwnd.prefer_CF_TEXT) { for (i = 0 ; i < numfe ; i++) { if (fel[i].cfFormat == CF_TEXT) { NeedToChooseFormat = false; IndexOfDataToInsert = i; break; } } } if (NeedToChooseFormat) { dialog<DragDropDlg> params; params.allowable_effects = dwOKEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE); params.effect = copying; params.formatetcs = fel; params.numformatetcs = numfe; params.formats = NULL; params.numformats = 0; int ret = params.DoModal(hexwnd.pwnd); if (ret < 0) { //An error occured or the user canceled the operation err = S_OK; *pdwEffect = DROPEFFECT_NONE; goto ERR_ENUM; } numformats = params.numformats; formats = params.formats; copying = params.effect; } else if (NeedToChooseMoveorCopy) { int choice = PopupDropMenu(pt); if (choice == 0) { err = S_OK; *pdwEffect = DROPEFFECT_NONE; goto ERR_ENUM; } copying = choice != 1; } if (IndexOfDataToInsert >= 0 && formats == NULL) { formats = (UINT*)&IndexOfDataToInsert; numformats = 1; } //for each selected format for (i = 0 ; i < numformats ; i++) { FORMATETC fe = fel[formats[i]]; /*It is important that when debugging (with M$VC at least) you do not step __into__ the below GetData call If you do the app providing the data source will die & GetData will return OLE_E_NOTRUNNING or E_FAIL The solution is to step over the call It is also possible that a debugger will be opened & attach itself to the data provider */ if (pDataObject->GetData(&fe, &stm) == S_OK) { //Get len size_t len = 0; switch (stm.tymed) { case TYMED_HGLOBAL: len = GlobalSize(stm.hGlobal); break; #ifndef __CYGWIN__ case TYMED_FILE: { int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY); if (fh != -1) { len = _filelength(fh); if (len == (size_t)-1) len = 0; _close(fh); } } break; #endif //__CYGWIN__ case TYMED_ISTREAM: { STATSTG stat; if (S_OK == stm.pstm->Stat(&stat, STATFLAG_NONAME)) len = (size_t)stat.cbSize.LowPart; } break; //This case is going to be a bitch to implement so it can wait for a while //It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets case TYMED_ISTORAGE: { MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK); } break; // IStorage* case TYMED_GDI: { len = GetObject(stm.hBitmap, 0, NULL); if (len) { DIBSECTION t; GetObject(stm.hBitmap, len, &t); len += t.dsBm.bmHeight*t.dsBm.bmWidthBytes*t.dsBm.bmPlanes; } } break; // HBITMAP case TYMED_MFPICT: { len = GlobalSize(stm.hMetaFilePict); METAFILEPICT *pMFP = (METAFILEPICT*)GlobalLock(stm.hMetaFilePict); if (pMFP) { len += GetMetaFileBitsEx(pMFP->hMF, 0, NULL); GlobalUnlock(stm.hMetaFilePict); } } break; // HMETAFILE #ifndef __CYGWIN__ case TYMED_ENHMF: { len = GetEnhMetaFileHeader(stm.hEnhMetaFile, 0, NULL); DWORD n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile, 0, NULL); if (n && n != GDI_ERROR) len += sizeof(WCHAR) * n; len += GetEnhMetaFileBits(stm.hEnhMetaFile, 0, NULL); n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL); if (n && n != GDI_ERROR) len += sizeof(LOGPALETTE) + (n - 1) * sizeof(PALETTEENTRY); } break; // HENHMETAFILE #endif //__CYGWIN__ //case TYMED_NULL:break; } if (!len) continue; /*Malloc We do this so that if the data access fails we only need free(data) and don't need to mess around with the m_dataArray. Perhaps in the future the m_dataArray can support undoable actions.*/ BYTE* t = (BYTE*)realloc(data, len); if (!t) continue; data = t; memset(data, 0, len); //Get data switch (stm.tymed) { case TYMED_HGLOBAL: { if (LPVOID pmem = GlobalLock(stm.hGlobal)) { memcpy(data, pmem, len); gotdata = true; GlobalUnlock(stm.hGlobal); } } break; #ifndef __CYGWIN__ case TYMED_FILE: { int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY); if (fh != -1) { if (0 < _read(fh, data, len)) gotdata = true; _close(fh); } } break; #endif //__CYGWIN__ case TYMED_ISTREAM: { LARGE_INTEGER zero = { 0 }; ULARGE_INTEGER pos; if (S_OK == stm.pstm->Seek(zero, STREAM_SEEK_CUR, &pos)) { stm.pstm->Seek(zero, STREAM_SEEK_SET, NULL); if (S_OK == stm.pstm->Read(data, len, NULL)) gotdata = true; stm.pstm->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_SET, NULL); } } break; //This case is going to be a bitch to implement so it can wait for a while //It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets case TYMED_ISTORAGE: { MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK); goto ERR_ENUM; } break;//IStorage* case TYMED_GDI: { int l = GetObject(stm.hBitmap, len, data); if (l) { BITMAP* bm = (BITMAP*)data; if (bm->bmBits) memcpy(&data[l], bm->bmBits, len-l); else GetBitmapBits(stm.hBitmap, len-l, &data[l]); gotdata = true; } } break; // HBITMAP case TYMED_MFPICT: { if (METAFILEPICT *pMFP = (METAFILEPICT *)GlobalLock(stm.hMetaFilePict)) { memcpy(data, pMFP, sizeof *pMFP); GetMetaFileBitsEx(pMFP->hMF, len - sizeof(*pMFP), &data[sizeof(*pMFP)]); GlobalUnlock(stm.hMetaFilePict); gotdata = true; } } break;//HMETAFILE #ifndef __CYGWIN__ case TYMED_ENHMF: { DWORD i = 0, n = 0, l = len; n = GetEnhMetaFileHeader(stm.hEnhMetaFile, l, (ENHMETAHEADER*)&data[i]); l -= n; i += n; n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile, l / sizeof(WCHAR), (LPWSTR)&data[i]); if (n && n != GDI_ERROR) { n *= sizeof(WCHAR);l -= n; i += n; } n = GetEnhMetaFileBits(stm.hEnhMetaFile, l, &data[i]); l -= n; i += n; n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL); if (n && n != GDI_ERROR) { LOGPALETTE* lp = (LOGPALETTE*)&data[i]; lp->palVersion = 0x300; lp->palNumEntries = (USHORT)n; l -= sizeof(lp->palVersion) + sizeof(lp->palNumEntries); n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, l / sizeof(PALETTEENTRY), &lp->palPalEntry[0]); i += n*sizeof(PALETTEENTRY); } if (i) gotdata = true; } break; // HENHMETAFILE #endif //__CYGWIN__ //case TYMED_NULL:break; } ReleaseStgMedium(&stm); if (gotdata) { BYTE* DataToInsert = data; if (fe.cfFormat == CF_BINARYDATA) { len = *(DWORD*)data; DataToInsert += 4; } else if (fe.cfFormat == CF_TEXT || fe.cfFormat == CF_OEMTEXT) { len = strlen((char*)data); } else if (fe.cfFormat == CF_UNICODETEXT) { len = sizeof(wchar_t)*wcslen((wchar_t*)data); } // Insert/overwrite data into m_dataArray if (grfKeyState&MK_SHIFT) { /* Overwite */ SimpleArray<BYTE> olddata; DWORD upper = 1 + hexwnd.m_dataArray.GetUpperBound(); if (hexwnd.new_pos+len > upper) { olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], upper - hexwnd.new_pos + (int)totallen); /* Need more space */ if (hexwnd.m_dataArray.SetSize(hexwnd.new_pos + totallen + len)) { hexwnd.m_dataArray.ExpandToSize(); memcpy(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], DataToInsert, len); hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len); gotdata = true; totallen += len; } } else { /* Enough space */ olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], len); memcpy(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], DataToInsert, len); hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len); gotdata = true; totallen += len; } } else if (hexwnd.m_dataArray.InsertAtGrow(hexwnd.new_pos + totallen, DataToInsert, 0, len)) { /* Insert */ hexwnd.push_undorecord(hexwnd.new_pos + totallen, NULL, 0, DataToInsert, len); gotdata = true; totallen += len; } } } } // For each selected format // Release the data free(data); data = NULL; if (IndexOfDataToInsert < 0) { free(formats); formats = NULL; } if (gotdata) { hexwnd.iStartOfSelection = hexwnd.new_pos; hexwnd.iEndOfSelection = hexwnd.new_pos + totallen - 1; hexwnd.bFilestatusChanged = true; hexwnd.bSelected = true; hexwnd.resize_window(); hexwnd.synch_sibling(); } *pdwEffect = copying ? DROPEFFECT_COPY : DROPEFFECT_MOVE; err = S_OK; ERR_ENUM: iefe->Release(); free(fel); ERR: pDataObject->Release(); return err; } pDataObject->Release(); return S_OK; }
STDMETHODIMP VBoxDnDDropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { AssertPtrReturn(pDataObject, E_INVALIDARG); AssertPtrReturn(pdwEffect, E_INVALIDARG); LogFlowFunc(("pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld, dwEffect=%RU32\n", pDataObject, grfKeyState, pt.x, pt.y, *pdwEffect)); reset(); /** @todo At the moment we only support one DnD format at a time. */ /* Try different formats. CF_HDROP is the most common one, so start * with this. */ FORMATETC fmtEtc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/uri-list"; } else { LogFlowFunc(("CF_HDROP not wanted, hr=%Rhrc\n", hr)); /* So we couldn't retrieve the data in CF_HDROP format; try with * CF_UNICODETEXT + CF_TEXT formats now. Rest stays the same. */ fmtEtc.cfFormat = CF_UNICODETEXT; hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/plain;charset=utf-8"; } else { LogFlowFunc(("CF_UNICODETEXT not wanted, hr=%Rhrc\n", hr)); fmtEtc.cfFormat = CF_TEXT; hr = pDataObject->QueryGetData(&fmtEtc); if (hr == S_OK) { mFormats = "text/plain;charset=utf-8"; } else { LogFlowFunc(("CF_TEXT not wanted, hr=%Rhrc\n", hr)); fmtEtc.cfFormat = 0; /* Mark it to not supported. */ } } } /* Did we find a format that we support? */ if (fmtEtc.cfFormat) { LogFlowFunc(("Found supported format %RI16 (%s)\n", fmtEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(fmtEtc.cfFormat))); /* Make a copy of the FORMATETC structure so that we later can * use this for comparrison and stuff. */ /** Note: The DVTARGETDEVICE member only is a shallow copy for now! */ memcpy(&mFormatEtc, &fmtEtc, sizeof(FORMATETC)); /* Which drop effect we're going to use? */ /* Note: pt is not used since we don't need to differentiate within our * proxy window. */ *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect); } else { /* No or incompatible data -- so no drop effect required. */ *pdwEffect = DROPEFFECT_NONE; switch (hr) { case ERROR_INVALID_FUNCTION: { LogRel(("DnD: Drag and drop format is not supported by VBoxTray\n")); /* Enumerate supported source formats. This shouldn't happen too often * on day to day use, but still keep it in here. */ IEnumFORMATETC *pEnumFormats; HRESULT hr2 = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormats); if (SUCCEEDED(hr2)) { LogRel(("DnD: The following formats were offered to us:\n")); FORMATETC curFormatEtc; while (pEnumFormats->Next(1, &curFormatEtc, NULL /* pceltFetched */) == S_OK) { WCHAR wszCfName[128]; /* 128 chars should be enough, rest will be truncated. */ hr2 = GetClipboardFormatNameW(curFormatEtc.cfFormat, wszCfName, sizeof(wszCfName) / sizeof(WCHAR)); LogRel(("\tcfFormat=%RI16 (%s), tyMed=%RI32, dwAspect=%RI32, strCustomName=%ls, hr=%Rhrc\n", curFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(curFormatEtc.cfFormat), curFormatEtc.tymed, curFormatEtc.dwAspect, wszCfName, hr2)); } pEnumFormats->Release(); } break; } default: break; } } LogFlowFunc(("Returning cfFormat=%RI16, pdwEffect=%ld, hr=%Rhrc\n", fmtEtc.cfFormat, *pdwEffect, hr)); return hr; }