/* 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();
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
// 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);
}
Esempio n. 5
0
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();
		}
	}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}