barrier/src/lib/platform/MSWindowsDropTarget.cpp

179 lines
4.1 KiB
C++

/*
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2014-2016 Symless Ltd.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "platform/MSWindowsDropTarget.h"
#include "base/Log.h"
#include "common/common.h"
#include <stdio.h>
#include <Shlobj.h>
void getDropData(IDataObject *pDataObject);
MSWindowsDropTarget* MSWindowsDropTarget::s_instance = NULL;
MSWindowsDropTarget::MSWindowsDropTarget() :
m_refCount(1),
m_allowDrop(false)
{
s_instance = this;
}
MSWindowsDropTarget::~MSWindowsDropTarget()
{
}
MSWindowsDropTarget&
MSWindowsDropTarget::instance()
{
assert(s_instance != NULL);
return *s_instance;
}
HRESULT
MSWindowsDropTarget::DragEnter(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect)
{
// check if data object contain drop
m_allowDrop = queryDataObject(dataObject);
if (m_allowDrop) {
getDropData(dataObject);
}
*effect = DROPEFFECT_NONE;
return S_OK;
}
HRESULT
MSWindowsDropTarget::DragOver(DWORD keyState, POINTL point, DWORD* effect)
{
*effect = DROPEFFECT_NONE;
return S_OK;
}
HRESULT
MSWindowsDropTarget::DragLeave(void)
{
return S_OK;
}
HRESULT
MSWindowsDropTarget::Drop(IDataObject* dataObject, DWORD keyState, POINTL point, DWORD* effect)
{
*effect = DROPEFFECT_NONE;
return S_OK;
}
bool
MSWindowsDropTarget::queryDataObject(IDataObject* dataObject)
{
// check if it supports CF_HDROP using a HGLOBAL
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
return dataObject->QueryGetData(&fmtetc) == S_OK ? true : false;
}
void
MSWindowsDropTarget::setDraggingFilename(char* const filename)
{
m_dragFilename = filename;
}
std::string
MSWindowsDropTarget::getDraggingFilename()
{
return m_dragFilename;
}
void
MSWindowsDropTarget::clearDraggingFilename()
{
m_dragFilename.clear();
}
void
getDropData(IDataObject* dataObject)
{
// construct a FORMATETC object
FORMATETC fmtEtc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgMed;
// See if the dataobject contains any DROP stored as a HGLOBAL
if (dataObject->QueryGetData(&fmtEtc) == S_OK) {
if (dataObject->GetData(&fmtEtc, &stgMed) == S_OK) {
// get data here
PVOID data = GlobalLock(stgMed.hGlobal);
// data object global handler contains:
// DROPFILESfilename1 filename2 two spaces as the end
// TODO: get multiple filenames
wchar_t* wcData = (wchar_t*)((LPBYTE)data + sizeof(DROPFILES));
// convert wchar to char
char* filename = new char[wcslen(wcData) + 1];
filename[wcslen(wcData)] = '\0';
wcstombs(filename, wcData, wcslen(wcData));
MSWindowsDropTarget::instance().setDraggingFilename(filename);
GlobalUnlock(stgMed.hGlobal);
// release the data using the COM API
ReleaseStgMedium(&stgMed);
delete[] filename;
}
}
}
HRESULT __stdcall
MSWindowsDropTarget::QueryInterface (REFIID iid, void ** object)
{
if (iid == IID_IDropTarget || iid == IID_IUnknown) {
AddRef();
*object = this;
return S_OK;
}
else {
*object = 0;
return E_NOINTERFACE;
}
}
ULONG __stdcall
MSWindowsDropTarget::AddRef(void)
{
return InterlockedIncrement(&m_refCount);
}
ULONG __stdcall
MSWindowsDropTarget::Release(void)
{
LONG count = InterlockedDecrement(&m_refCount);
if (count == 0) {
delete this;
return 0;
}
else {
return count;
}
}