#include "config.h"
#endif
+#define CINTERFACE
+#define COBJMACROS
+
+#include <Ole2.h>
+#include <ShlObj.h>
+#include <Windows.h>
+#include <WinUser.h>
+
#include <assert.h>
#include <winpr/crt.h>
#define TAG CLIENT_TAG("windows")
+#ifdef WITH_DEBUG_CLIPRDR
+#define DEBUG_CLIPRDR(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_CLIPRDR(fmt, ...) do { } while (0)
+#endif
+
+struct format_mapping
+{
+ UINT32 remote_format_id;
+ UINT32 local_format_id;
+ WCHAR* name;
+};
+typedef struct format_mapping formatMapping;
+
+struct _CliprdrEnumFORMATETC
+{
+ IEnumFORMATETC iEnumFORMATETC;
+
+ LONG m_lRefCount;
+ LONG m_nIndex;
+ LONG m_nNumFormats;
+ FORMATETC* m_pFormatEtc;
+};
+typedef struct _CliprdrEnumFORMATETC CliprdrEnumFORMATETC;
+
+struct _CliprdrStream
+{
+ IStream iStream;
+
+ LONG m_lRefCount;
+ LONG m_lIndex;
+ ULARGE_INTEGER m_lSize;
+ ULARGE_INTEGER m_lOffset;
+ void* m_pData;
+};
+typedef struct _CliprdrStream CliprdrStream;
+
+struct _CliprdrDataObject
+{
+ IDataObject iDataObject;
+
+ LONG m_lRefCount;
+ FORMATETC* m_pFormatEtc;
+ STGMEDIUM* m_pStgMedium;
+ LONG m_nNumFormats;
+ LONG m_nStreams;
+ IStream** m_pStream;
+ void* m_pData;
+};
+typedef struct _CliprdrDataObject CliprdrDataObject;
+
+struct wf_clipboard
+{
+ wfContext* wfc;
+ rdpChannels* channels;
+ CliprdrClientContext* context;
+
+ BOOL sync;
+ UINT32 capabilities;
+
+ size_t map_size;
+ size_t map_capacity;
+ formatMapping* format_mappings;
+
+ UINT32 requestedFormatId;
+
+ HWND hwnd;
+ HANDLE hmem;
+ HANDLE thread;
+ HANDLE response_data_event;
+
+ LPDATAOBJECT data_obj;
+ ULONG req_fsize;
+ char* req_fdata;
+ HANDLE req_fevent;
+
+ size_t nFiles;
+ size_t file_array_size;
+ WCHAR** file_names;
+ FILEDESCRIPTORW** fileDescriptor;
+};
+typedef struct wf_clipboard wfClipboard;
+
extern BOOL WINAPI AddClipboardFormatListener(_In_ HWND hwnd);
extern BOOL WINAPI RemoveClipboardFormatListener(_In_ HWND hwnd);
#define WM_CLIPRDR_MESSAGE (WM_USER + 156)
#define OLE_SETCLIPBOARD 1
-BOOL wf_create_file_obj(wfClipboard* cliprdrrdr, IDataObject** ppDataObject);
-void wf_destroy_file_obj(IDataObject* instance);
+static BOOL wf_create_file_obj(wfClipboard* cliprdrrdr, IDataObject** ppDataObject);
+static void wf_destroy_file_obj(IDataObject* instance);
+static UINT32 get_remote_format_id(wfClipboard* clipboard, UINT32 local_format);
+static UINT cliprdr_send_data_request(wfClipboard* clipboard, UINT32 format);
+static UINT cliprdr_send_lock(wfClipboard* clipboard);
+static UINT cliprdr_send_unlock(wfClipboard* clipboard);
+static UINT cliprdr_send_request_filecontents(wfClipboard* clipboard, void* streamid,
+ int index, int flag, DWORD positionhigh,
+ DWORD positionlow, ULONG request);
+
+static void CliprdrDataObject_Delete(CliprdrDataObject* instance);
+
+static CliprdrEnumFORMATETC* CliprdrEnumFORMATETC_New(int nFormats, FORMATETC* pFormatEtc);
+static void CliprdrEnumFORMATETC_Delete(CliprdrEnumFORMATETC* instance);
+
+static void CliprdrStream_Delete(CliprdrStream* instance);
/**
* IStream
*/
-HRESULT STDMETHODCALLTYPE CliprdrStream_QueryInterface(IStream* This, REFIID riid, void** ppvObject)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_QueryInterface(IStream* This,
+ REFIID riid, void** ppvObject)
{
- CliprdrStream* instance = (CliprdrStream*) This;
-
if (IsEqualIID(riid, &IID_IStream) || IsEqualIID(riid, &IID_IUnknown))
{
IStream_AddRef(This);
}
}
-ULONG STDMETHODCALLTYPE CliprdrStream_AddRef(IStream* This)
+static ULONG STDMETHODCALLTYPE CliprdrStream_AddRef(IStream* This)
{
CliprdrStream* instance = (CliprdrStream*) This;
+ if (!instance)
+ return 0;
+
return InterlockedIncrement(&instance->m_lRefCount);
}
-ULONG STDMETHODCALLTYPE CliprdrStream_Release(IStream* This)
+static ULONG STDMETHODCALLTYPE CliprdrStream_Release(IStream* This)
{
LONG count;
CliprdrStream* instance = (CliprdrStream*) This;
+ if (!instance)
+ return 0;
+
count = InterlockedDecrement(&instance->m_lRefCount);
if (count == 0)
}
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream* This, void *pv, ULONG cb, ULONG *pcbRead)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream* This, void *pv,
+ ULONG cb, ULONG *pcbRead)
{
int ret;
CliprdrStream* instance = (CliprdrStream*) This;
- wfClipboard* clipboard = (wfClipboard*) instance->m_pData;
+ wfClipboard* clipboard;
- if (!pv || !pcbRead)
+ if (!pv || !pcbRead || !instance)
return E_INVALIDARG;
+ clipboard = (wfClipboard*) instance->m_pData;
*pcbRead = 0;
if (instance->m_lOffset.QuadPart >= instance->m_lSize.QuadPart)
- return E_FAIL;
+ return S_FALSE;
ret = cliprdr_send_request_filecontents(clipboard, (void*) This,
- instance->m_lIndex, FILECONTENTS_RANGE,
- instance->m_lOffset.HighPart, instance->m_lOffset.LowPart, cb);
+ instance->m_lIndex, FILECONTENTS_RANGE,
+ instance->m_lOffset.HighPart, instance->m_lOffset.LowPart, cb);
if (ret < 0)
return E_FAIL;
instance->m_lOffset.QuadPart += clipboard->req_fsize;
if (clipboard->req_fsize < cb)
- return E_FAIL;
+ return S_FALSE;
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Write(IStream* This, const void* pv, ULONG cb, ULONG *pcbWritten)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Write(IStream* This, const void* pv,
+ ULONG cb, ULONG *pcbWritten)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)pv;
+ (void)cb;
+ (void)pcbWritten;
return STG_E_ACCESSDENIED;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Seek(IStream* This, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Seek(IStream* This, LARGE_INTEGER dlibMove,
+ DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
{
ULONGLONG newoffset;
CliprdrStream* instance = (CliprdrStream*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
newoffset = instance->m_lOffset.QuadPart;
switch (dwOrigin)
{
- case STREAM_SEEK_SET:
- newoffset = dlibMove.QuadPart;
- break;
- case STREAM_SEEK_CUR:
- newoffset += dlibMove.QuadPart;
- break;
- case STREAM_SEEK_END:
- newoffset = instance->m_lSize.QuadPart + dlibMove.QuadPart;
- break;
- default:
- return E_INVALIDARG;
+ case STREAM_SEEK_SET:
+ newoffset = dlibMove.QuadPart;
+ break;
+ case STREAM_SEEK_CUR:
+ newoffset += dlibMove.QuadPart;
+ break;
+ case STREAM_SEEK_END:
+ newoffset = instance->m_lSize.QuadPart + dlibMove.QuadPart;
+ break;
+ default:
+ return E_INVALIDARG;
}
if (newoffset < 0 || newoffset >= instance->m_lSize.QuadPart)
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_SetSize(IStream* This, ULARGE_INTEGER libNewSize)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_SetSize(IStream* This,
+ ULARGE_INTEGER libNewSize)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)libNewSize;
- return STG_E_INSUFFICIENTMEMORY;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_CopyTo(IStream* This, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER *pcbWritten)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_CopyTo(IStream* This, IStream* pstm,
+ ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead,
+ ULARGE_INTEGER *pcbWritten)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)pstm;
+ (void)cb;
+ (void)pcbRead;
+ (void)pcbWritten;
- return S_OK;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Commit(IStream* This, DWORD grfCommitFlags)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Commit(IStream* This, DWORD grfCommitFlags)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)grfCommitFlags;
- return STG_E_MEDIUMFULL;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Revert(IStream* This)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Revert(IStream* This)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
- return STG_E_INSUFFICIENTMEMORY;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_LockRegion(IStream* This, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_LockRegion(IStream* This, ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb, DWORD dwLockType)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)libOffset;
+ (void)cb;
+ (void)dwLockType;
- return STG_E_INSUFFICIENTMEMORY;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_UnlockRegion(IStream* This, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_UnlockRegion(IStream* This, ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb, DWORD dwLockType)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)libOffset;
+ (void)cb;
+ (void)dwLockType;
- return STG_E_INSUFFICIENTMEMORY;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Stat(IStream* This, STATSTG* pstatstg, DWORD grfStatFlag)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Stat(IStream* This, STATSTG* pstatstg, DWORD grfStatFlag)
{
CliprdrStream* instance = (CliprdrStream*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
if (pstatstg == NULL)
return STG_E_INVALIDPOINTER;
switch (grfStatFlag)
{
- case STATFLAG_DEFAULT:
- return STG_E_INSUFFICIENTMEMORY;
+ case STATFLAG_DEFAULT:
+ return STG_E_INSUFFICIENTMEMORY;
- case STATFLAG_NONAME:
- pstatstg->cbSize.QuadPart = instance->m_lSize.QuadPart;
- pstatstg->grfLocksSupported = LOCK_EXCLUSIVE;
- pstatstg->grfMode = GENERIC_READ;
- pstatstg->grfStateBits = 0;
- pstatstg->type = STGTY_STREAM;
- break;
+ case STATFLAG_NONAME:
+ pstatstg->cbSize.QuadPart = instance->m_lSize.QuadPart;
+ pstatstg->grfLocksSupported = LOCK_EXCLUSIVE;
+ pstatstg->grfMode = GENERIC_READ;
+ pstatstg->grfStateBits = 0;
+ pstatstg->type = STGTY_STREAM;
+ break;
- case STATFLAG_NOOPEN:
- return STG_E_INVALIDFLAG;
+ case STATFLAG_NOOPEN:
+ return STG_E_INVALIDFLAG;
- default:
- return STG_E_INVALIDFLAG;
+ default:
+ return STG_E_INVALIDFLAG;
}
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrStream_Clone(IStream* This, IStream** ppstm)
+static HRESULT STDMETHODCALLTYPE CliprdrStream_Clone(IStream* This, IStream** ppstm)
{
- CliprdrStream* instance = (CliprdrStream*) This;
+ (void)This;
+ (void)ppstm;
- return STG_E_INSUFFICIENTMEMORY;
+ return E_NOTIMPL;
}
-CliprdrStream* CliprdrStream_New(LONG index, void* pData)
+static CliprdrStream* CliprdrStream_New(LONG index, void* pData)
{
IStream* iStream;
+ BOOL success = FALSE;
CliprdrStream* instance;
wfClipboard* clipboard = (wfClipboard*) pData;
instance->m_lOffset.QuadPart = 0;
/* get content size of this stream */
- cliprdr_send_request_filecontents(clipboard, (void*) instance,
- instance->m_lIndex, FILECONTENTS_SIZE, 0, 0, 8);
+ if (cliprdr_send_request_filecontents(clipboard, (void*) instance,
+ instance->m_lIndex,
+ FILECONTENTS_SIZE, 0, 0, 8) == CHANNEL_RC_OK)
+ {
+ success = TRUE;
+ }
+
instance->m_lSize.QuadPart = *((LONGLONG*) clipboard->req_fdata);
free(clipboard->req_fdata);
}
- else
- {
- free(instance);
- instance = NULL;
- }
+ }
+
+ if (!success)
+ {
+ CliprdrStream_Delete(instance);
+ instance = NULL;
}
return instance;
{
int i;
+ if (!instance || !pFormatEtc)
+ return -1;
+
for (i = 0; i < instance->m_nNumFormats; i++)
{
if ((pFormatEtc->tymed & instance->m_pFormatEtc[i].tymed) &&
- pFormatEtc->cfFormat == instance->m_pFormatEtc[i].cfFormat &&
- pFormatEtc->dwAspect == instance->m_pFormatEtc[i].dwAspect)
+ pFormatEtc->cfFormat == instance->m_pFormatEtc[i].cfFormat &&
+ pFormatEtc->dwAspect & instance->m_pFormatEtc[i].dwAspect)
{
return i;
}
return -1;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_QueryInterface(IDataObject* This, REFIID riid, void** ppvObject)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_QueryInterface(
+ IDataObject* This, REFIID riid, void** ppvObject)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+
+ if (!ppvObject)
+ return E_INVALIDARG;
if (IsEqualIID(riid, &IID_IDataObject) || IsEqualIID(riid, &IID_IUnknown))
{
}
}
-ULONG STDMETHODCALLTYPE CliprdrDataObject_AddRef(IDataObject* This)
+static ULONG STDMETHODCALLTYPE CliprdrDataObject_AddRef(IDataObject* This)
{
CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
return InterlockedIncrement(&instance->m_lRefCount);
}
-ULONG STDMETHODCALLTYPE CliprdrDataObject_Release(IDataObject* This)
+static ULONG STDMETHODCALLTYPE CliprdrDataObject_Release(IDataObject* This)
{
LONG count;
CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
count = InterlockedDecrement(&instance->m_lRefCount);
if (count == 0)
return 0;
}
else
- {
return count;
- }
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject* This, FORMATETC* pFormatEtc, STGMEDIUM* pMedium)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(
+ IDataObject* This, FORMATETC* pFormatEtc, STGMEDIUM* pMedium)
{
int i, idx;
CliprdrDataObject* instance = (CliprdrDataObject*) This;
- wfClipboard* clipboard = (wfClipboard*) instance->m_pData;
+ wfClipboard* clipboard;
- if (!pFormatEtc || !pMedium)
- {
+ if (!pFormatEtc || !pMedium || !instance)
+ return E_INVALIDARG;
+
+ clipboard = clipboard = (wfClipboard*) instance->m_pData;
+
+ if (!clipboard)
return E_INVALIDARG;
- }
if ((idx = cliprdr_lookup_format(instance, pFormatEtc)) == -1)
- {
return DV_E_FORMATETC;
- }
pMedium->tymed = instance->m_pFormatEtc[idx].tymed;
pMedium->pUnkForRelease = 0;
- if (instance->m_pFormatEtc[idx].cfFormat == clipboard->ID_FILEDESCRIPTORW)
+ if (instance->m_pFormatEtc[idx].cfFormat == RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW))
{
- if (cliprdr_send_data_request(clipboard, instance->m_pFormatEtc[idx].cfFormat) != 0)
+ DWORD remote = get_remote_format_id(clipboard, instance->m_pFormatEtc[idx].cfFormat);
+ if (cliprdr_send_data_request(clipboard, remote) != 0)
return E_UNEXPECTED;
pMedium->hGlobal = clipboard->hmem; /* points to a FILEGROUPDESCRIPTOR structure */
/* GlobalLock returns a pointer to the first byte of the memory block,
* in which is a FILEGROUPDESCRIPTOR structure, whose first UINT member
* is the number of FILEDESCRIPTOR's */
- instance->m_nStreams = *((PUINT) GlobalLock(clipboard->hmem));
+ FILEGROUPDESCRIPTOR *dsc = (FILEGROUPDESCRIPTOR*) GlobalLock(clipboard->hmem);
+ instance->m_nStreams = dsc->cItems;
GlobalUnlock(clipboard->hmem);
if (instance->m_nStreams > 0)
if (instance->m_pStream)
{
for (i = 0; i < instance->m_nStreams; i++)
- {
instance->m_pStream[i] = (IStream*) CliprdrStream_New(i, clipboard);
- }
}
}
}
return E_OUTOFMEMORY;
}
}
- else if (instance->m_pFormatEtc[idx].cfFormat == clipboard->ID_FILECONTENTS)
+ else if (instance->m_pFormatEtc[idx].cfFormat == RegisterClipboardFormat(CFSTR_FILECONTENTS))
{
if (pFormatEtc->lindex < instance->m_nStreams)
{
IDataObject_AddRef(instance->m_pStream[pFormatEtc->lindex]);
}
else
- {
return E_INVALIDARG;
- }
- }
- else if (instance->m_pFormatEtc[idx].cfFormat == clipboard->ID_PREFERREDDROPEFFECT)
- {
- if (cliprdr_send_data_request(clipboard, instance->m_pFormatEtc[idx].cfFormat) != 0)
- return E_UNEXPECTED;
-
- pMedium->hGlobal = clipboard->hmem;
}
else
- {
return E_UNEXPECTED;
- }
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetDataHere(IDataObject* This, FORMATETC* pformatetc, STGMEDIUM* pmedium)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetDataHere(
+ IDataObject* This, FORMATETC* pformatetc, STGMEDIUM* pmedium)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)pformatetc;
+ (void)pmedium;
- return DATA_E_FORMATETC;
+ return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_QueryGetData(IDataObject* This, FORMATETC* pformatetc)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_QueryGetData(
+ IDataObject* This, FORMATETC* pformatetc)
{
CliprdrDataObject* instance = (CliprdrDataObject*) This;
if (!pformatetc)
return E_INVALIDARG;
- return (cliprdr_lookup_format(instance, pformatetc) == -1) ? DV_E_FORMATETC : S_OK;
+ if (cliprdr_lookup_format(instance, pformatetc) == -1)
+ return DV_E_FORMATETC;
+
+ return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetCanonicalFormatEtc(IDataObject* This, FORMATETC* pformatectIn, FORMATETC* pformatetcOut)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetCanonicalFormatEtc(
+ IDataObject* This, FORMATETC* pformatectIn, FORMATETC* pformatetcOut)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)pformatectIn;
if (!pformatetcOut)
return E_INVALIDARG;
return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_SetData(IDataObject* This, FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_SetData(
+ IDataObject* This, FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)pformatetc;
+ (void)pmedium;
+ (void)fRelease;
return E_NOTIMPL;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_EnumFormatEtc(IDataObject* This, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_EnumFormatEtc(
+ IDataObject* This, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
{
CliprdrDataObject* instance = (CliprdrDataObject*) This;
- if (!ppenumFormatEtc)
+ if (!instance || !ppenumFormatEtc)
return E_INVALIDARG;
if (dwDirection == DATADIR_GET)
}
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_DAdvise(IDataObject* This, FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_DAdvise(
+ IDataObject* This, FORMATETC* pformatetc, DWORD advf,
+ IAdviseSink* pAdvSink, DWORD* pdwConnection)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)pformatetc;
+ (void)advf;
+ (void)pAdvSink;
+ (void)pdwConnection;
return OLE_E_ADVISENOTSUPPORTED;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_DUnadvise(IDataObject* This, DWORD dwConnection)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_DUnadvise(
+ IDataObject* This, DWORD dwConnection)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)dwConnection;
return OLE_E_ADVISENOTSUPPORTED;
}
-HRESULT STDMETHODCALLTYPE CliprdrDataObject_EnumDAdvise(IDataObject* This, IEnumSTATDATA** ppenumAdvise)
+static HRESULT STDMETHODCALLTYPE CliprdrDataObject_EnumDAdvise(
+ IDataObject* This, IEnumSTATDATA** ppenumAdvise)
{
- CliprdrDataObject* instance = (CliprdrDataObject*) This;
+ (void)This;
+ (void)ppenumAdvise;
return OLE_E_ADVISENOTSUPPORTED;
}
-CliprdrDataObject* CliprdrDataObject_New(FORMATETC* fmtetc, STGMEDIUM* stgmed, int count, void* data)
+static CliprdrDataObject* CliprdrDataObject_New(
+ FORMATETC* fmtetc, STGMEDIUM* stgmed, int count, void* data)
{
int i;
CliprdrDataObject* instance;
instance = (CliprdrDataObject*) calloc(1, sizeof(CliprdrDataObject));
- if (instance)
- {
- iDataObject = &instance->iDataObject;
-
- iDataObject->lpVtbl = (IDataObjectVtbl*) calloc(1, sizeof(IDataObjectVtbl));
+ if (!instance)
+ goto error;
- if (iDataObject->lpVtbl)
- {
- iDataObject->lpVtbl->QueryInterface = CliprdrDataObject_QueryInterface;
- iDataObject->lpVtbl->AddRef = CliprdrDataObject_AddRef;
- iDataObject->lpVtbl->Release = CliprdrDataObject_Release;
- iDataObject->lpVtbl->GetData = CliprdrDataObject_GetData;
- iDataObject->lpVtbl->GetDataHere = CliprdrDataObject_GetDataHere;
- iDataObject->lpVtbl->QueryGetData = CliprdrDataObject_QueryGetData;
- iDataObject->lpVtbl->GetCanonicalFormatEtc = CliprdrDataObject_GetCanonicalFormatEtc;
- iDataObject->lpVtbl->SetData = CliprdrDataObject_SetData;
- iDataObject->lpVtbl->EnumFormatEtc = CliprdrDataObject_EnumFormatEtc;
- iDataObject->lpVtbl->DAdvise = CliprdrDataObject_DAdvise;
- iDataObject->lpVtbl->DUnadvise = CliprdrDataObject_DUnadvise;
- iDataObject->lpVtbl->EnumDAdvise = CliprdrDataObject_EnumDAdvise;
+ iDataObject = &instance->iDataObject;
- instance->m_lRefCount = 1;
- instance->m_nNumFormats = count;
- instance->m_pData = data;
- instance->m_nStreams = 0;
- instance->m_pStream = NULL;
+ iDataObject->lpVtbl = (IDataObjectVtbl*) calloc(1, sizeof(IDataObjectVtbl));
- instance->m_pFormatEtc = (FORMATETC*) calloc(count, sizeof(FORMATETC));
- instance->m_pStgMedium = (STGMEDIUM*) calloc(count, sizeof(STGMEDIUM));
+ if (!iDataObject->lpVtbl)
+ goto error;
- for (i = 0; i < count; i++)
- {
- instance->m_pFormatEtc[i] = fmtetc[i];
- instance->m_pStgMedium[i] = stgmed[i];
- }
- }
- else
+ iDataObject->lpVtbl->QueryInterface = CliprdrDataObject_QueryInterface;
+ iDataObject->lpVtbl->AddRef = CliprdrDataObject_AddRef;
+ iDataObject->lpVtbl->Release = CliprdrDataObject_Release;
+ iDataObject->lpVtbl->GetData = CliprdrDataObject_GetData;
+ iDataObject->lpVtbl->GetDataHere = CliprdrDataObject_GetDataHere;
+ iDataObject->lpVtbl->QueryGetData = CliprdrDataObject_QueryGetData;
+ iDataObject->lpVtbl->GetCanonicalFormatEtc = CliprdrDataObject_GetCanonicalFormatEtc;
+ iDataObject->lpVtbl->SetData = CliprdrDataObject_SetData;
+ iDataObject->lpVtbl->EnumFormatEtc = CliprdrDataObject_EnumFormatEtc;
+ iDataObject->lpVtbl->DAdvise = CliprdrDataObject_DAdvise;
+ iDataObject->lpVtbl->DUnadvise = CliprdrDataObject_DUnadvise;
+ iDataObject->lpVtbl->EnumDAdvise = CliprdrDataObject_EnumDAdvise;
+
+ instance->m_lRefCount = 1;
+ instance->m_nNumFormats = count;
+ instance->m_pData = data;
+ instance->m_nStreams = 0;
+ instance->m_pStream = NULL;
+
+ if (count > 0)
+ {
+ instance->m_pFormatEtc = (FORMATETC*) calloc(count, sizeof(FORMATETC));
+ if (!instance->m_pFormatEtc)
+ goto error;
+ instance->m_pStgMedium = (STGMEDIUM*) calloc(count, sizeof(STGMEDIUM));
+ if (!instance->m_pStgMedium)
+ goto error;
+
+ for (i = 0; i < count; i++)
{
- free(instance);
- instance = NULL;
+ instance->m_pFormatEtc[i] = fmtetc[i];
+ instance->m_pStgMedium[i] = stgmed[i];
}
}
return instance;
+
+error:
+ CliprdrDataObject_Delete(instance);
+ return NULL;
}
void CliprdrDataObject_Delete(CliprdrDataObject* instance)
if (instance->m_pStream)
{
- int i;
+ LONG i;
for (i = 0; i < instance->m_nStreams; i++)
- {
CliprdrStream_Release(instance->m_pStream[i]);
- }
free(instance->m_pStream);
}
}
}
-BOOL wf_create_file_obj(wfClipboard* clipboard, IDataObject** ppDataObject)
+static BOOL wf_create_file_obj(wfClipboard* clipboard, IDataObject** ppDataObject)
{
- FORMATETC fmtetc[3];
- STGMEDIUM stgmeds[3];
+ FORMATETC fmtetc[2];
+ STGMEDIUM stgmeds[2];
if (!ppDataObject)
return FALSE;
- fmtetc[0].cfFormat = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW);
+ fmtetc[0].cfFormat = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
fmtetc[0].dwAspect = DVASPECT_CONTENT;
fmtetc[0].lindex = 0;
fmtetc[0].ptd = NULL;
stgmeds[0].hGlobal = NULL;
stgmeds[0].pUnkForRelease = NULL;
- fmtetc[1].cfFormat = RegisterClipboardFormatW(CFSTR_FILECONTENTS);
+ fmtetc[1].cfFormat = RegisterClipboardFormat(CFSTR_FILECONTENTS);
fmtetc[1].dwAspect = DVASPECT_CONTENT;
fmtetc[1].lindex = 0;
fmtetc[1].ptd = NULL;
stgmeds[1].pstm = NULL;
stgmeds[1].pUnkForRelease = NULL;
- fmtetc[2].cfFormat = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT);
- fmtetc[2].dwAspect = DVASPECT_CONTENT;
- fmtetc[2].lindex = 0;
- fmtetc[2].ptd = NULL;
- fmtetc[2].tymed = TYMED_HGLOBAL;
-
- stgmeds[2].tymed = TYMED_HGLOBAL;
- stgmeds[2].hGlobal = NULL;
- stgmeds[2].pUnkForRelease = NULL;
-
- *ppDataObject = (IDataObject*) CliprdrDataObject_New(fmtetc, stgmeds, 3, clipboard);
+ *ppDataObject = (IDataObject*) CliprdrDataObject_New(fmtetc, stgmeds, 2, clipboard);
return (*ppDataObject) ? TRUE : FALSE;
}
-void wf_destroy_file_obj(IDataObject* instance)
+static void wf_destroy_file_obj(IDataObject* instance)
{
if (instance)
IDataObject_Release(instance);
if (source->ptd)
{
dest->ptd = (DVTARGETDEVICE*) CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
- *(dest->ptd) = *(source->ptd);
+ if (dest->ptd)
+ *(dest->ptd) = *(source->ptd);
}
}
-HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_QueryInterface(IEnumFORMATETC* This, REFIID riid, void** ppvObject)
+static HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_QueryInterface(
+ IEnumFORMATETC* This, REFIID riid, void** ppvObject)
{
- CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
+ (void)This;
if (IsEqualIID(riid, &IID_IEnumFORMATETC) || IsEqualIID(riid, &IID_IUnknown))
{
}
}
-ULONG STDMETHODCALLTYPE CliprdrEnumFORMATETC_AddRef(IEnumFORMATETC* This)
+static ULONG STDMETHODCALLTYPE CliprdrEnumFORMATETC_AddRef(IEnumFORMATETC* This)
{
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
+ if (!instance)
+ return 0;
+
return InterlockedIncrement(&instance->m_lRefCount);
}
-ULONG STDMETHODCALLTYPE CliprdrEnumFORMATETC_Release(IEnumFORMATETC* This)
+static ULONG STDMETHODCALLTYPE CliprdrEnumFORMATETC_Release(IEnumFORMATETC* This)
{
LONG count;
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
+ if (!instance)
+ return 0;
+
count = InterlockedDecrement(&instance->m_lRefCount);
if (count == 0)
}
}
-HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Next(IEnumFORMATETC* This, ULONG celt, FORMATETC* rgelt, ULONG* pceltFetched)
+static HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Next(IEnumFORMATETC* This, ULONG celt,
+ FORMATETC* rgelt, ULONG* pceltFetched)
{
ULONG copied = 0;
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
- if (!celt || !rgelt)
+ if (!instance || !celt || !rgelt)
return E_INVALIDARG;
while ((instance->m_nIndex < instance->m_nNumFormats) && (copied < celt))
return (copied == celt) ? S_OK : E_FAIL;
}
-HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Skip(IEnumFORMATETC* This, ULONG celt)
+static HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Skip(IEnumFORMATETC* This, ULONG celt)
{
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
if (instance->m_nIndex + (LONG) celt > instance->m_nNumFormats)
return E_FAIL;
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Reset(IEnumFORMATETC* This)
+static HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Reset(IEnumFORMATETC* This)
{
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
+ if (!instance)
+ return E_INVALIDARG;
+
instance->m_nIndex = 0;
return S_OK;
}
-HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Clone(IEnumFORMATETC* This, IEnumFORMATETC **ppEnum)
+static HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Clone(IEnumFORMATETC* This, IEnumFORMATETC **ppEnum)
{
CliprdrEnumFORMATETC* instance = (CliprdrEnumFORMATETC*) This;
- if (!ppEnum)
+ if (!instance || !ppEnum)
return E_INVALIDARG;
*ppEnum = (IEnumFORMATETC*) CliprdrEnumFORMATETC_New(instance->m_nNumFormats, instance->m_pFormatEtc);
CliprdrEnumFORMATETC* instance;
IEnumFORMATETC* iEnumFORMATETC;
- if (!pFormatEtc)
+ if ((nFormats != 0) && !pFormatEtc)
return NULL;
instance = (CliprdrEnumFORMATETC*) calloc(1, sizeof(CliprdrEnumFORMATETC));
- if (instance)
- {
- iEnumFORMATETC = &instance->iEnumFORMATETC;
+ if (!instance)
+ goto error;
- iEnumFORMATETC->lpVtbl = (IEnumFORMATETCVtbl*) calloc(1, sizeof(IEnumFORMATETCVtbl));
+ iEnumFORMATETC = &instance->iEnumFORMATETC;
- if (iEnumFORMATETC->lpVtbl)
- {
- iEnumFORMATETC->lpVtbl->QueryInterface = CliprdrEnumFORMATETC_QueryInterface;
- iEnumFORMATETC->lpVtbl->AddRef = CliprdrEnumFORMATETC_AddRef;
- iEnumFORMATETC->lpVtbl->Release = CliprdrEnumFORMATETC_Release;
- iEnumFORMATETC->lpVtbl->Next = CliprdrEnumFORMATETC_Next;
- iEnumFORMATETC->lpVtbl->Skip = CliprdrEnumFORMATETC_Skip;
- iEnumFORMATETC->lpVtbl->Reset = CliprdrEnumFORMATETC_Reset;
- iEnumFORMATETC->lpVtbl->Clone = CliprdrEnumFORMATETC_Clone;
-
- instance->m_lRefCount = 0;
- instance->m_nIndex = 0;
- instance->m_nNumFormats = nFormats;
- instance->m_pFormatEtc = (FORMATETC*) calloc(nFormats, sizeof(FORMATETC));
-
- for (i = 0; i < nFormats; i++)
- {
- cliprdr_format_deep_copy(&instance->m_pFormatEtc[i], &pFormatEtc[i]);
- }
- }
- else
- {
- free(instance);
- instance = NULL;
- }
- }
+ iEnumFORMATETC->lpVtbl = (IEnumFORMATETCVtbl*) calloc(1, sizeof(IEnumFORMATETCVtbl));
+
+ if (!iEnumFORMATETC->lpVtbl)
+ goto error;
+
+ iEnumFORMATETC->lpVtbl->QueryInterface = CliprdrEnumFORMATETC_QueryInterface;
+ iEnumFORMATETC->lpVtbl->AddRef = CliprdrEnumFORMATETC_AddRef;
+ iEnumFORMATETC->lpVtbl->Release = CliprdrEnumFORMATETC_Release;
+ iEnumFORMATETC->lpVtbl->Next = CliprdrEnumFORMATETC_Next;
+ iEnumFORMATETC->lpVtbl->Skip = CliprdrEnumFORMATETC_Skip;
+ iEnumFORMATETC->lpVtbl->Reset = CliprdrEnumFORMATETC_Reset;
+ iEnumFORMATETC->lpVtbl->Clone = CliprdrEnumFORMATETC_Clone;
+
+ instance->m_lRefCount = 0;
+ instance->m_nIndex = 0;
+ instance->m_nNumFormats = nFormats;
+ if (nFormats > 0)
+ {
+ instance->m_pFormatEtc = (FORMATETC*) calloc(nFormats, sizeof(FORMATETC));
+ if (!instance->m_pFormatEtc)
+ goto error;
+ for (i = 0; i < nFormats; i++)
+ cliprdr_format_deep_copy(&instance->m_pFormatEtc[i], &pFormatEtc[i]);
+ }
return instance;
+
+error:
+ CliprdrEnumFORMATETC_Delete(instance);
+ return NULL;
}
void CliprdrEnumFORMATETC_Delete(CliprdrEnumFORMATETC* instance)
{
- int i;
+ LONG i;
if (instance)
{
/***********************************************************************************/
-static UINT32 get_local_format_id_by_name(wfClipboard* clipboard, void* format_name)
+static UINT32 get_local_format_id_by_name(wfClipboard* clipboard, const TCHAR* format_name)
{
- int i;
+ size_t i;
formatMapping* map;
+ WCHAR* unicode_name;
+#if !defined(UNICODE)
+ size_t size;
+#endif
+
+ if (!clipboard || !format_name)
+ return 0;
+
+#if defined(UNICODE)
+ unicode_name = _wcsdup(format_name);
+#else
+ size = _tcslen(format_name);
+ unicode_name = calloc(size + 1, sizeof(WCHAR));
+ if (!unicode_name)
+ return 0;
+
+ MultiByteToWideChar(CP_OEMCP, 0, format_name, strlen(format_name), unicode_name, size);
+#endif
+ if (!unicode_name)
+ return 0;
for (i = 0; i < clipboard->map_size; i++)
{
map = &clipboard->format_mappings[i];
-
- if ((clipboard->capabilities & CB_USE_LONG_FORMAT_NAMES) != 0)
+ if (map->name)
{
- if (map->name)
+ if (wcscmp(map->name, unicode_name) == 0)
{
- if (memcmp(map->name, format_name, wcslen((LPCWSTR) format_name)) == 0)
- return map->local_format_id;
+ free (unicode_name);
+ return map->local_format_id;
}
}
}
+ free (unicode_name);
return 0;
}
static INLINE BOOL file_transferring(wfClipboard* clipboard)
{
- return get_local_format_id_by_name(clipboard, _T("FileGroupDescriptorW")) ? TRUE : FALSE;
+ return get_local_format_id_by_name(clipboard, CFSTR_FILEDESCRIPTORW) ? TRUE : FALSE;
}
static UINT32 get_remote_format_id(wfClipboard* clipboard, UINT32 local_format)
{
- int i;
+ UINT32 i;
formatMapping* map;
+ if (!clipboard)
+ return 0;
+
for (i = 0; i < clipboard->map_size; i++)
{
map = &clipboard->format_mappings[i];
if (map->local_format_id == local_format)
- {
return map->remote_format_id;
- }
}
return local_format;
static void map_ensure_capacity(wfClipboard* clipboard)
{
+ if (!clipboard)
+ return;
+
if (clipboard->map_size >= clipboard->map_capacity)
{
- int new_size;
+ size_t new_size;
formatMapping *new_map;
new_size = clipboard->map_capacity * 2;
new_map = (formatMapping*) realloc(clipboard->format_mappings,
- sizeof(formatMapping) * new_size);
+ sizeof(formatMapping) * new_size);
if (!new_map)
return;
clipboard->format_mappings = new_map;
}
}
-static void clear_format_map(wfClipboard* clipboard)
+static BOOL clear_format_map(wfClipboard* clipboard)
{
- int i;
+ size_t i;
formatMapping* map;
+ if (!clipboard)
+ return FALSE;
+
if (clipboard->format_mappings)
{
for (i = 0; i < clipboard->map_capacity; i++)
}
clipboard->map_size = 0;
+ return TRUE;
}
-int cliprdr_send_tempdir(wfClipboard* clipboard)
+static UINT cliprdr_send_tempdir(wfClipboard* clipboard)
{
CLIPRDR_TEMP_DIRECTORY tempDirectory;
- GetEnvironmentVariableA("TEMP", tempDirectory.szTempDir, sizeof(tempDirectory.szTempDir));
+ if (!clipboard)
+ return -1;
- clipboard->context->TempDirectory(clipboard->context, &tempDirectory);
+ if (GetEnvironmentVariableA("TEMP", tempDirectory.szTempDir, sizeof(tempDirectory.szTempDir)) == 0)
+ return -1;
- return 1;
+ return clipboard->context->TempDirectory(clipboard->context, &tempDirectory);
}
-static int cliprdr_send_format_list(wfClipboard* clipboard)
+static UINT cliprdr_send_format_list(wfClipboard* clipboard)
{
+ UINT rc;
int count;
- int length;
UINT32 index;
UINT32 numFormats;
UINT32 formatId = 0;
char formatName[1024];
- CLIPRDR_FORMAT* format;
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
+ if (!clipboard)
+ return ERROR_INTERNAL_ERROR;
+
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
if (!OpenClipboard(clipboard->hwnd))
- return -1;
+ return ERROR_INTERNAL_ERROR;
count = CountClipboardFormats();
numFormats = (UINT32) count;
formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT));
+ if (!formats)
+ {
+ CloseClipboard();
+ return CHANNEL_RC_NO_MEMORY;
+ }
index = 0;
while (formatId = EnumClipboardFormats(formatId))
- {
- format = &formats[index++];
-
- format->formatId = formatId;
+ formats[index++].formatId = formatId;;
- length = 0;
- format->formatName = NULL;
+ numFormats = index;
- if (formatId >= CF_MAX)
- {
- length = GetClipboardFormatNameA(formatId, formatName, sizeof(formatName) - 1);
- }
-
- if (length > 0)
- {
- format->formatName = _strdup(formatName);
- }
+ if (!CloseClipboard())
+ {
+ free (formats);
+ return ERROR_INTERNAL_ERROR;
}
- CloseClipboard();
+ for (index = 0; index < numFormats; index++)
+ {
+ GetClipboardFormatNameA(formats[index].formatId, formatName, sizeof(formatName));
+ formats[index].formatName = _strdup(formatName);
+ }
- formatList.msgFlags = 0;
formatList.numFormats = numFormats;
formatList.formats = formats;
- clipboard->context->ClientFormatList(clipboard->context, &formatList);
+ rc = clipboard->context->ClientFormatList(clipboard->context, &formatList);
for (index = 0; index < numFormats; index++)
- {
- format = &formats[index];
- free(format->formatName);
- }
+ free(formats[index].formatName);
free(formats);
- return 1;
+ return rc;
}
-int cliprdr_send_data_request(wfClipboard* clipboard, UINT32 formatId)
+static UINT cliprdr_send_data_request(wfClipboard* clipboard, UINT32 formatId)
{
+ UINT rc;
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
+ if (!clipboard || !clipboard->context ||
+ !clipboard->context->ClientFormatDataRequest)
+ return ERROR_INTERNAL_ERROR;
+
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.msgFlags = CB_RESPONSE_OK;
formatDataRequest.requestedFormatId = formatId;
clipboard->requestedFormatId = formatId;
- clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest);
+ rc = clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest);
- WaitForSingleObject(clipboard->response_data_event, INFINITE);
- ResetEvent(clipboard->response_data_event);
+ if (WaitForSingleObject(clipboard->response_data_event, INFINITE) != WAIT_OBJECT_0)
+ rc = ERROR_INTERNAL_ERROR;
+ else if (!ResetEvent(clipboard->response_data_event))
+ rc = ERROR_INTERNAL_ERROR;
- return 0;
+ return rc;
}
-int cliprdr_send_request_filecontents(wfClipboard* clipboard, void* streamid,
- int index, int flag, DWORD positionhigh, DWORD positionlow, ULONG nreq)
+static UINT cliprdr_send_request_filecontents(wfClipboard* clipboard, const void* streamid,
+ int index, int flag, DWORD positionhigh,
+ DWORD positionlow, ULONG nreq)
{
+ UINT rc;
CLIPRDR_FILE_CONTENTS_REQUEST fileContentsRequest;
- ZeroMemory(&fileContentsRequest, sizeof(CLIPRDR_FILE_CONTENTS_REQUEST));
+ if (!clipboard || !clipboard->context ||
+ !clipboard->context->ClientFileContentsRequest)
+ return ERROR_INTERNAL_ERROR;
fileContentsRequest.streamId = (UINT32) streamid;
fileContentsRequest.listIndex = index;
fileContentsRequest.cbRequested = nreq;
fileContentsRequest.clipDataId = 0;
- clipboard->context->ClientFileContentsRequest(clipboard->context, &fileContentsRequest);
+ rc = clipboard->context->ClientFileContentsRequest(clipboard->context, &fileContentsRequest);
- WaitForSingleObject(clipboard->req_fevent, INFINITE);
- ResetEvent(clipboard->req_fevent);
+ if (WaitForSingleObject(clipboard->req_fevent, INFINITE) != WAIT_OBJECT_0)
+ rc = ERROR_INTERNAL_ERROR;
+ else if (!ResetEvent(clipboard->req_fevent))
+ rc = ERROR_INTERNAL_ERROR;
- return 0;
+ return rc;
}
-int cliprdr_send_response_filecontents(wfClipboard* clipboard, UINT32 streamId, UINT32 size, BYTE* data)
+static UINT cliprdr_send_response_filecontents(wfClipboard* clipboard,
+ UINT32 streamId, UINT32 size,
+ BYTE* data)
{
CLIPRDR_FILE_CONTENTS_RESPONSE fileContentsResponse;
- ZeroMemory(&fileContentsResponse, sizeof(CLIPRDR_FILE_CONTENTS_RESPONSE));
+ if (!clipboard || !clipboard->context ||
+ !clipboard->context->ClientFileContentsResponse)
+ return ERROR_INTERNAL_ERROR;
fileContentsResponse.streamId = streamId;
fileContentsResponse.cbRequested = size;
fileContentsResponse.requestedData = data;
-
- clipboard->context->ClientFileContentsResponse(clipboard->context, &fileContentsResponse);
+ fileContentsResponse.msgFlags = CB_RESPONSE_OK;
- return 0;
+ return clipboard->context->ClientFileContentsResponse(clipboard->context, &fileContentsResponse);
}
static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
switch (Msg)
{
- case WM_CREATE:
- DEBUG_CLIPRDR("info: WM_CREATE");
- clipboard = (wfClipboard*)((CREATESTRUCT*) lParam)->lpCreateParams;
- if (!AddClipboardFormatListener(hWnd)) {
- DEBUG_CLIPRDR("error: AddClipboardFormatListener failed with %#x.", GetLastError());
- }
- clipboard->hwnd = hWnd;
- break;
+ case WM_CREATE:
+ DEBUG_CLIPRDR("info: WM_CREATE");
+ clipboard = (wfClipboard*)((CREATESTRUCT*) lParam)->lpCreateParams;
+ if (!AddClipboardFormatListener(hWnd)) {
+ DEBUG_CLIPRDR("error: AddClipboardFormatListener failed with %#x.", GetLastError());
+ }
+ clipboard->hwnd = hWnd;
+ break;
- case WM_CLOSE:
- DEBUG_CLIPRDR("info: WM_CLOSE");
- RemoveClipboardFormatListener(hWnd);
- break;
+ case WM_CLOSE:
+ DEBUG_CLIPRDR("info: WM_CLOSE");
+ RemoveClipboardFormatListener(hWnd);
+ break;
- case WM_CLIPBOARDUPDATE:
- DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
- if (clipboard->sync)
- {
- if ((GetClipboardOwner() != clipboard->hwnd) &&
+ case WM_CLIPBOARDUPDATE:
+ DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
+ if (clipboard->sync)
+ {
+ if ((GetClipboardOwner() != clipboard->hwnd) &&
(S_FALSE == OleIsCurrentClipboard(clipboard->data_obj)))
+ {
+ if (clipboard->hmem)
{
- if (clipboard->hmem)
- {
- GlobalFree(clipboard->hmem);
- clipboard->hmem = NULL;
- }
-
- cliprdr_send_format_list(clipboard);
+ GlobalFree(clipboard->hmem);
+ clipboard->hmem = NULL;
}
+
+ cliprdr_send_format_list(clipboard);
}
+ }
+ break;
+
+ case WM_RENDERALLFORMATS:
+ DEBUG_CLIPRDR("info: WM_RENDERALLFORMATS");
+ /* discard all contexts in clipboard */
+ if (!OpenClipboard(clipboard->hwnd))
+ {
+ DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
break;
+ }
+ EmptyClipboard();
+ CloseClipboard();
+ break;
- case WM_RENDERALLFORMATS:
- DEBUG_CLIPRDR("info: WM_RENDERALLFORMATS");
- /* discard all contexts in clipboard */
- if (!OpenClipboard(clipboard->hwnd))
- {
- DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
- break;
- }
- EmptyClipboard();
- CloseClipboard();
+ case WM_RENDERFORMAT:
+ DEBUG_CLIPRDR("info: WM_RENDERFORMAT");
+ if (cliprdr_send_data_request(clipboard, (UINT32) wParam) != 0)
+ {
+ DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
break;
+ }
- case WM_RENDERFORMAT:
- DEBUG_CLIPRDR("info: WM_RENDERFORMAT");
- if (cliprdr_send_data_request(clipboard, (UINT32) wParam) != 0)
+ if (!SetClipboardData((UINT) wParam, clipboard->hmem))
+ {
+ DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError());
+
+ if (clipboard->hmem)
{
- DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
- break;
+ GlobalFree(clipboard->hmem);
+ clipboard->hmem = NULL;
}
+ }
+ /* Note: GlobalFree() is not needed when success */
+ break;
- if (!SetClipboardData((UINT) wParam, clipboard->hmem))
+ case WM_CLIPRDR_MESSAGE:
+ DEBUG_CLIPRDR("info: WM_CLIPRDR_MESSAGE");
+ switch (wParam)
+ {
+ case OLE_SETCLIPBOARD:
+ DEBUG_CLIPRDR("info: OLE_SETCLIPBOARD");
+ if (wf_create_file_obj(clipboard, &clipboard->data_obj))
{
- DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError());
-
- if (clipboard->hmem)
+ if (OleSetClipboard(clipboard->data_obj) != S_OK)
{
- GlobalFree(clipboard->hmem);
- clipboard->hmem = NULL;
+ wf_destroy_file_obj(clipboard->data_obj);
+ clipboard->data_obj = NULL;
}
}
- /* Note: GlobalFree() is not needed when success */
break;
- case WM_CLIPRDR_MESSAGE:
- DEBUG_CLIPRDR("info: WM_CLIPRDR_MESSAGE");
- switch (wParam)
- {
- case OLE_SETCLIPBOARD:
- DEBUG_CLIPRDR("info: OLE_SETCLIPBOARD");
- if (wf_create_file_obj(clipboard, &clipboard->data_obj))
- {
- if (OleSetClipboard(clipboard->data_obj) != S_OK)
- {
- wf_destroy_file_obj(clipboard->data_obj);
- clipboard->data_obj = NULL;
- }
- }
- break;
-
- default:
- break;
- }
+ default:
break;
+ }
+ break;
- case WM_DESTROYCLIPBOARD:
- case WM_ASKCBFORMATNAME:
- case WM_HSCROLLCLIPBOARD:
- case WM_PAINTCLIPBOARD:
- case WM_SIZECLIPBOARD:
- case WM_VSCROLLCLIPBOARD:
- default:
- return DefWindowProc(hWnd, Msg, wParam, lParam);
+ case WM_DESTROYCLIPBOARD:
+ case WM_ASKCBFORMATNAME:
+ case WM_HSCROLLCLIPBOARD:
+ case WM_PAINTCLIPBOARD:
+ case WM_SIZECLIPBOARD:
+ case WM_VSCROLLCLIPBOARD:
+ default:
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
RegisterClassEx(&wnd_cls);
clipboard->hwnd = CreateWindowEx(WS_EX_LEFT,
- _T("ClipboardHiddenMessageProcessor"),
- _T("rdpclip"),
- 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), clipboard);
+ _T("ClipboardHiddenMessageProcessor"),
+ _T("rdpclip"),
+ 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), clipboard);
if (!clipboard->hwnd)
{
static void clear_file_array(wfClipboard* clipboard)
{
- int i;
+ size_t i;
+
+ if (!clipboard)
+ return;
/* clear file_names array */
if (clipboard->file_names)
free(clipboard->file_names[i]);
clipboard->file_names[i] = NULL;
}
+
+ free (clipboard->file_names);
+ clipboard->file_names = NULL;
}
/* clear fileDescriptor array */
free(clipboard->fileDescriptor[i]);
clipboard->fileDescriptor[i] = NULL;
}
+ free (clipboard->fileDescriptor);
+ clipboard->fileDescriptor = NULL;
}
+ clipboard->file_array_size = 0;
clipboard->nFiles = 0;
}
static BOOL wf_cliprdr_get_file_contents(WCHAR* file_name, BYTE* buffer,
- int positionLow, int positionHigh, int nRequested, unsigned int* puSize)
+ LONG positionLow, LONG positionHigh,
+ DWORD nRequested, DWORD* puSize)
{
+ BOOL res = FALSE;
HANDLE hFile;
- DWORD nGet;
+ DWORD nGet, rc;
if (!file_name || !buffer || !puSize)
{
WLog_ERR(TAG, "get file contents Invalid Arguments.");
return FALSE;
}
-
+
hFile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
-
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
+
if (hFile == INVALID_HANDLE_VALUE)
- {
return FALSE;
- }
- SetFilePointer(hFile, positionLow, (PLONG) &positionHigh, FILE_BEGIN);
+ rc = SetFilePointer(hFile, positionLow, &positionHigh, FILE_BEGIN);
+ if (rc == INVALID_SET_FILE_POINTER)
+ goto error;
if (!ReadFile(hFile, buffer, nRequested, &nGet, NULL))
{
DWORD err = GetLastError();
DEBUG_CLIPRDR("ReadFile failed with 0x%x.", err);
+ goto error;
}
- CloseHandle(hFile);
+ res = TRUE;
+
+error:
+ if (!CloseHandle(hFile))
+ res = FALSE;
- *puSize = nGet;
+ if (res)
+ *puSize = nGet;
- return TRUE;
+ return res;
}
/* path_name has a '\' at the end. e.g. c:\newfolder\, file_name is c:\newfolder\new.txt */
-static FILEDESCRIPTORW* wf_cliprdr_get_file_descriptor(WCHAR* file_name, int pathLen)
+static FILEDESCRIPTORW* wf_cliprdr_get_file_descriptor(WCHAR* file_name, size_t pathLen)
{
HANDLE hFile;
FILEDESCRIPTORW* fd;
return NULL;
hFile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return fd;
}
-static void wf_cliprdr_array_ensure_capacity(wfClipboard* clipboard)
+static BOOL wf_cliprdr_array_ensure_capacity(wfClipboard* clipboard)
{
+ if (!clipboard)
+ return FALSE;
+
if (clipboard->nFiles == clipboard->file_array_size)
{
- int new_size;
+ size_t new_size;
FILEDESCRIPTORW **new_fd;
WCHAR **new_name;
- new_size = clipboard->file_array_size * 2;
+ new_size = (clipboard->file_array_size + 1) * 2;
- new_fd = (FILEDESCRIPTORW**) realloc(clipboard->fileDescriptor, new_size * sizeof(FILEDESCRIPTORW*));
+ new_fd = (FILEDESCRIPTORW**) realloc(clipboard->fileDescriptor,
+ new_size * sizeof(FILEDESCRIPTORW*));
if (new_fd)
clipboard->fileDescriptor = new_fd;
clipboard->file_names = new_name;
if (!new_fd || !new_name)
- return;
+ return FALSE;
- clipboard->file_array_size *= new_size;
+ clipboard->file_array_size = new_size;
}
+
+ return TRUE;
}
-static void wf_cliprdr_add_to_file_arrays(wfClipboard* clipboard, WCHAR* full_file_name, int pathLen)
+static BOOL wf_cliprdr_add_to_file_arrays(wfClipboard* clipboard,
+ WCHAR* full_file_name, size_t pathLen)
{
+ if (!wf_cliprdr_array_ensure_capacity(clipboard))
+ return FALSE;
+
/* add to name array */
clipboard->file_names[clipboard->nFiles] = (LPWSTR) malloc(MAX_PATH * 2);
+ if (!clipboard->file_names[clipboard->nFiles])
+ return FALSE;
+
wcscpy_s(clipboard->file_names[clipboard->nFiles], MAX_PATH, full_file_name);
/* add to descriptor array */
- clipboard->fileDescriptor[clipboard->nFiles] = wf_cliprdr_get_file_descriptor(full_file_name, pathLen);
+ clipboard->fileDescriptor[clipboard->nFiles] =
+ wf_cliprdr_get_file_descriptor(full_file_name, pathLen);
+ if (!clipboard->fileDescriptor[clipboard->nFiles])
+ {
+ free (clipboard->file_names[clipboard->nFiles]);
+ return FALSE;
+ }
clipboard->nFiles++;
- wf_cliprdr_array_ensure_capacity(clipboard);
+ return TRUE;
}
-static void wf_cliprdr_traverse_directory(wfClipboard* clipboard, WCHAR* Dir, int pathLen)
+static BOOL wf_cliprdr_traverse_directory(wfClipboard* clipboard,
+ WCHAR* Dir, size_t pathLen)
{
HANDLE hFind;
WCHAR DirSpec[MAX_PATH];
WIN32_FIND_DATA FindFileData;
+ if (!clipboard || !Dir)
+ return FALSE;
+
StringCchCopy(DirSpec, MAX_PATH, Dir);
StringCchCat(DirSpec, MAX_PATH, TEXT("\\*"));
if (hFind == INVALID_HANDLE_VALUE)
{
DEBUG_CLIPRDR("FindFirstFile failed with 0x%x.", GetLastError());
- return;
+ return FALSE;
}
while (FindNextFile(hFind, &FindFileData))
{
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0
- && wcscmp(FindFileData.cFileName, _T(".")) == 0
- || wcscmp(FindFileData.cFileName, _T("..")) == 0)
+ && wcscmp(FindFileData.cFileName, _T(".")) == 0
+ || wcscmp(FindFileData.cFileName, _T("..")) == 0)
{
continue;
}
StringCchCopy(DirAdd, MAX_PATH, Dir);
StringCchCat(DirAdd, MAX_PATH, _T("\\"));
StringCchCat(DirAdd, MAX_PATH, FindFileData.cFileName);
- wf_cliprdr_add_to_file_arrays(clipboard, DirAdd, pathLen);
- wf_cliprdr_traverse_directory(clipboard, DirAdd, pathLen);
+ if (!wf_cliprdr_add_to_file_arrays(clipboard, DirAdd, pathLen))
+ return FALSE;
+ if (!wf_cliprdr_traverse_directory(clipboard, DirAdd, pathLen))
+ return FALSE;
}
else
{
StringCchCat(fileName, MAX_PATH, _T("\\"));
StringCchCat(fileName, MAX_PATH, FindFileData.cFileName);
- wf_cliprdr_add_to_file_arrays(clipboard, fileName, pathLen);
+ if (!wf_cliprdr_add_to_file_arrays(clipboard, fileName, pathLen))
+ return FALSE;
}
}
FindClose(hFind);
+
+ return TRUE;
}
-int wf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
+static UINT wf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
{
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
+ if (!clipboard || !clipboard->context ||
+ !clipboard->context->ClientCapabilities)
+ return ERROR_INTERNAL_ERROR;
+
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = CB_CAPS_VERSION_2;
- generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
-
- clipboard->context->ClientCapabilities(clipboard->context, &capabilities);
+ generalCapabilitySet.generalFlags =
+ CB_USE_LONG_FORMAT_NAMES |
+ CB_STREAM_FILECLIP_ENABLED |
+ CB_FILECLIP_NO_FILE_PATHS |
+ CB_CAN_LOCK_CLIPDATA;
- return 1;
+ return clipboard->context->ClientCapabilities(clipboard->context, &capabilities);
}
/**
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_monitor_ready(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady)
+static UINT wf_cliprdr_monitor_ready(CliprdrClientContext* context,
+ CLIPRDR_MONITOR_READY* monitorReady)
{
+ UINT rc;
wfClipboard* clipboard = (wfClipboard*) context->custom;
+ if (!context || !monitorReady)
+ return ERROR_INTERNAL_ERROR;
+
clipboard->sync = TRUE;
- wf_cliprdr_send_client_capabilities(clipboard);
- cliprdr_send_format_list(clipboard);
+ rc = wf_cliprdr_send_client_capabilities(clipboard);
+ if (rc != CHANNEL_RC_OK)
+ return rc;
- return CHANNEL_RC_OK;
+ return cliprdr_send_format_list(clipboard);
}
/**
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_server_capabilities(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities)
+static UINT wf_cliprdr_server_capabilities(CliprdrClientContext* context,
+ CLIPRDR_CAPABILITIES* capabilities)
{
UINT32 index;
CLIPRDR_CAPABILITY_SET* capabilitySet;
wfClipboard* clipboard = (wfClipboard*) context->custom;
+ if (!context || !capabilities)
+ return ERROR_INTERNAL_ERROR;
+
for (index = 0; index < capabilities->cCapabilitiesSets; index++)
{
capabilitySet = &(capabilities->capabilitySets[index]);
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
- (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
+ (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
{
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet
- = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
+ = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
clipboard->capabilities = generalCapabilitySet->generalFlags;
break;
}
}
-
+
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList)
+static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_LIST* formatList)
{
- UINT32 i, j;
+ UINT rc = ERROR_INTERNAL_ERROR;
+ UINT32 i;
formatMapping* mapping;
CLIPRDR_FORMAT* format;
wfClipboard* clipboard = (wfClipboard*) context->custom;
- clear_format_map(clipboard);
+ if (!clear_format_map(clipboard))
+ return ERROR_INTERNAL_ERROR;
- for (i = j = 0; i < formatList->numFormats; i++)
+ for (i = 0; i < formatList->numFormats; i++)
{
format = &(formatList->formats[i]);
- mapping = &(clipboard->format_mappings[j++]);
+ mapping = &(clipboard->format_mappings[i]);
mapping->remote_format_id = format->formatId;
if (format->formatName)
{
- mapping->name = _strdup(format->formatName);
- mapping->local_format_id = RegisterClipboardFormatA((LPCSTR) mapping->name);
+ int size = MultiByteToWideChar(CP_UTF8, 0, format->formatName, strlen(format->formatName),
+ NULL, 0);
+ mapping->name = calloc(size + 1, sizeof(WCHAR));
+ if (mapping->name)
+ {
+ MultiByteToWideChar(CP_UTF8, 0, format->formatName, strlen(format->formatName),
+ mapping->name, size);
+ mapping->local_format_id = RegisterClipboardFormatW((LPWSTR) mapping->name);
+ }
}
else
{
if (file_transferring(clipboard))
{
- PostMessage(clipboard->hwnd, WM_CLIPRDR_MESSAGE, OLE_SETCLIPBOARD, 0);
+ if (PostMessage(clipboard->hwnd, WM_CLIPRDR_MESSAGE, OLE_SETCLIPBOARD, 0))
+ rc = CHANNEL_RC_OK;
}
else
{
if (EmptyClipboard())
{
for (i = 0; i < (UINT32) clipboard->map_size; i++)
- {
SetClipboardData(clipboard->format_mappings[i].local_format_id, NULL);
- }
+ rc = CHANNEL_RC_OK;
}
- CloseClipboard();
+ if (!CloseClipboard() && GetLastError())
+ return ERROR_INTERNAL_ERROR;
}
- return CHANNEL_RC_OK;
+ return rc;
}
/**
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
+static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ (void)context;
+ (void)formatListResponse;
+
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT wf_cliprdr_server_lock_clipboard_data(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
+static UINT wf_cliprdr_server_lock_clipboard_data(CliprdrClientContext* context,
+ CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ (void)context;
+ (void)lockClipboardData;
+
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT wf_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
+static UINT wf_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* context,
+ CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ (void)context;
+ (void)unlockClipboardData;
+
return CHANNEL_RC_OK;
}
+static BOOL wf_cliprdr_process_filename(wfClipboard* clipboard,
+ WCHAR* wFileName, size_t str_len)
+{
+ size_t pathLen;
+ size_t offset = str_len;
+
+ if (!clipboard || !wFileName)
+ return FALSE;
+
+ /* find the last '\' in full file name */
+ while(offset > 0)
+ {
+ if (wFileName[offset] == L'\\')
+ break;
+ else
+ offset--;
+ }
+
+ pathLen = offset + 1;
+
+ if (!wf_cliprdr_add_to_file_arrays(clipboard, wFileName, pathLen))
+ return FALSE;
+
+ if ((clipboard->fileDescriptor[clipboard->nFiles - 1]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ {
+ /* this is a directory */
+ if (!wf_cliprdr_traverse_directory(clipboard, wFileName, pathLen))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
+static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
- int size = 0;
- char* buff = NULL;
+ UINT rc;
+ size_t size = 0;
+ void* buff = NULL;
char* globlemem = NULL;
HANDLE hClipdata = NULL;
UINT32 requestedFormatId;
CLIPRDR_FORMAT_DATA_RESPONSE response;
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ wfClipboard* clipboard;
+
+ if (!context || !formatDataRequest)
+ return ERROR_INTERNAL_ERROR;
+
+ clipboard = (wfClipboard*) context->custom;
+
+ if (!clipboard)
+ return ERROR_INTERNAL_ERROR;
requestedFormatId = formatDataRequest->requestedFormatId;
- if (requestedFormatId == RegisterClipboardFormatW(_T("FileGroupDescriptorW")))
+ if (requestedFormatId == RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW))
{
- int len;
- int i;
+ size_t len;
+ size_t i;
WCHAR* wFileName;
- unsigned int uSize;
HRESULT result;
LPDATAOBJECT dataObj;
FORMATETC format_etc;
STGMEDIUM stg_medium;
DROPFILES* dropFiles;
+ FILEGROUPDESCRIPTORW* groupDsc;
result = OleGetClipboard(&dataObj);
ZeroMemory(&format_etc, sizeof(FORMATETC));
ZeroMemory(&stg_medium, sizeof(STGMEDIUM));
- /* try to get FileGroupDescriptorW struct from OLE */
- format_etc.cfFormat = requestedFormatId;
+ /* get DROPFILES struct from OLE */
+ format_etc.cfFormat = CF_HDROP;
format_etc.tymed = TYMED_HGLOBAL;
format_etc.dwAspect = 1;
format_etc.lindex = -1;
- format_etc.ptd = 0;
result = IDataObject_GetData(dataObj, &format_etc, &stg_medium);
- if (SUCCEEDED(result))
+ if (FAILED(result)) {
+ DEBUG_CLIPRDR("dataObj->GetData failed.");
+ goto exit;
+ }
+
+ dropFiles = (DROPFILES*) GlobalLock(stg_medium.hGlobal);
+
+ if (!dropFiles)
{
- DEBUG_CLIPRDR("Got FileGroupDescriptorW.");
- globlemem = (char*) GlobalLock(stg_medium.hGlobal);
- uSize = GlobalSize(stg_medium.hGlobal);
- size = uSize;
- buff = (char*) malloc(uSize);
- CopyMemory(buff, globlemem, uSize);
GlobalUnlock(stg_medium.hGlobal);
ReleaseStgMedium(&stg_medium);
+ clipboard->nFiles = 0;
- clear_file_array(clipboard);
+ goto exit;
}
- else
- {
- /* get DROPFILES struct from OLE */
- format_etc.cfFormat = CF_HDROP;
- format_etc.tymed = TYMED_HGLOBAL;
- format_etc.dwAspect = 1;
- format_etc.lindex = -1;
-
- result = IDataObject_GetData(dataObj, &format_etc, &stg_medium);
-
- if (FAILED(result)) {
- DEBUG_CLIPRDR("dataObj->GetData failed.");
- }
- globlemem = (char*) GlobalLock(stg_medium.hGlobal);
+ clear_file_array(clipboard);
- if (!globlemem)
+ if (dropFiles->fWide)
+ {
+ /* dropFiles contains file names */
+ for (wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles);
+ (len = wcslen(wFileName)) > 0; wFileName += len + 1)
{
- GlobalUnlock(stg_medium.hGlobal);
-
- ReleaseStgMedium(&stg_medium);
- clipboard->nFiles = 0;
-
- goto exit;
+ wf_cliprdr_process_filename(clipboard, wFileName, wcslen(wFileName));
}
- uSize = GlobalSize(stg_medium.hGlobal);
-
- dropFiles = (DROPFILES*) malloc(uSize);
- memcpy(dropFiles, globlemem, uSize);
-
- GlobalUnlock(stg_medium.hGlobal);
-
- ReleaseStgMedium(&stg_medium);
-
- clear_file_array(clipboard);
+ }
+ else
+ {
+ char* p;
- if (dropFiles->fWide)
+ for (p = (char*)((char*)dropFiles + dropFiles->pFiles);
+ (len = strlen(p)) > 0; p += len + 1, clipboard->nFiles++)
{
- WCHAR* p;
- int str_len;
- int offset;
- int pathLen;
+ int cchWideChar;
+ WCHAR *wFileName;
- /* dropFiles contains file names */
- for (wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles); (len = wcslen(wFileName)) > 0; wFileName += len + 1)
- {
- /* get path name */
- str_len = wcslen(wFileName);
- offset = str_len;
- /* find the last '\' in full file name */
- for (p = wFileName + offset; *p != L'\\'; p--)
- {
- ;
- }
- p += 1;
- pathLen = wcslen(wFileName) - wcslen(p);
-
- wf_cliprdr_add_to_file_arrays(clipboard, wFileName, pathLen);
+ cchWideChar = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, NULL, 0);
+ wFileName = (LPWSTR) calloc(cchWideChar, sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, wFileName, cchWideChar);
- if ((clipboard->fileDescriptor[clipboard->nFiles - 1]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
- {
- /* this is a directory */
- wf_cliprdr_traverse_directory(clipboard, wFileName, pathLen);
- }
- }
+ wf_cliprdr_process_filename(clipboard, wFileName, cchWideChar);
}
- else
- {
- char* p;
+ }
- for (p = (char*)((char*)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0; p += len + 1, clipboard->nFiles++)
- {
- int cchWideChar;
+ GlobalUnlock(stg_medium.hGlobal);
- cchWideChar = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, NULL, 0);
- clipboard->file_names[clipboard->nFiles] = (LPWSTR) malloc(cchWideChar * 2);
- MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, clipboard->file_names[clipboard->nFiles], cchWideChar);
-
- map_ensure_capacity(clipboard);
- }
- }
+ ReleaseStgMedium(&stg_medium);
exit:
- size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
- buff = (char*) malloc(size);
-
- *((UINT32*) buff) = clipboard->nFiles;
-
+ size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
+ groupDsc = (FILEGROUPDESCRIPTORW*) malloc(size);
+ if (groupDsc)
+ {
+ groupDsc->cItems = clipboard->nFiles;
for (i = 0; i < clipboard->nFiles; i++)
{
if (clipboard->fileDescriptor[i])
- {
- memcpy(buff + 4 + i * sizeof(FILEDESCRIPTORW), clipboard->fileDescriptor[i], sizeof(FILEDESCRIPTORW));
- }
+ groupDsc->fgd[i] = *clipboard->fileDescriptor[i];
}
+ buff = groupDsc;
}
-
IDataObject_Release(dataObj);
}
else
globlemem = (char*) GlobalLock(hClipdata);
size = (int) GlobalSize(hClipdata);
- buff = (char*) malloc(size);
+ buff = malloc(size);
CopyMemory(buff, globlemem, size);
GlobalUnlock(hClipdata);
response.dataLen = size;
response.requestedFormatData = (BYTE*) buff;
- clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
+ rc = clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
free(buff);
- return CHANNEL_RC_OK;
+ return rc;
}
/**
*
* @return 0 on success, otherwise a Win32 error code
*/
-static UINT wf_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
+static UINT wf_cliprdr_server_format_data_response(CliprdrClientContext* context,
+ CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
BYTE* data;
HANDLE hMem;
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ wfClipboard* clipboard;
+
+ if (!context || !formatDataResponse)
+ return ERROR_INTERNAL_ERROR;
+
+ clipboard = (wfClipboard*) context->custom;
+
+ if (!clipboard)
+ return ERROR_INTERNAL_ERROR;
+
+ hMem = GlobalAlloc(GMEM_MOVEABLE, formatDataResponse->dataLen);
+ if (!hMem)
+ return ERROR_INTERNAL_ERROR;
- hMem = GlobalAlloc(GMEM_FIXED, formatDataResponse->dataLen);
data = (BYTE*) GlobalLock(hMem);
+ if (!data)
+ {
+ GlobalFree(hMem);
+ return ERROR_INTERNAL_ERROR;
+ }
+
CopyMemory(data, formatDataResponse->requestedFormatData, formatDataResponse->dataLen);
- GlobalUnlock(hMem);
+ if (!GlobalUnlock(hMem) && GetLastError())
+ {
+ GlobalFree(hMem);
+ return ERROR_INTERNAL_ERROR;
+ }
clipboard->hmem = hMem;
- SetEvent(clipboard->response_data_event);
+ if (!SetEvent(clipboard->response_data_event))
+ return ERROR_INTERNAL_ERROR;
return CHANNEL_RC_OK;
}
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
+static UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
+ CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
- UINT32 uSize = 0;
+ DWORD uSize = 0;
BYTE* pData = NULL;
HRESULT hRet = S_OK;
FORMATETC vFormatEtc;
LPDATAOBJECT pDataObj = NULL;
STGMEDIUM vStgMedium;
- LPSTREAM pStream = NULL;
BOOL bIsStreamFile = TRUE;
static LPSTREAM pStreamStc = NULL;
static UINT32 uStreamIdStc = 0;
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ wfClipboard* clipboard;
+ UINT rc = ERROR_INTERNAL_ERROR;
+ UINT sRc;
+
+ if (!context || !fileContentsRequest)
+ return ERROR_INTERNAL_ERROR;
+
+ clipboard = (wfClipboard*) context->custom;
+
+ if (!clipboard)
+ return ERROR_INTERNAL_ERROR;
if (fileContentsRequest->dwFlags == FILECONTENTS_SIZE)
fileContentsRequest->cbRequested = sizeof(UINT64);
pData = (BYTE*) calloc(1, fileContentsRequest->cbRequested);
-
+
if (!pData)
goto error;
WLog_ERR(TAG, "filecontents: get ole clipboard failed.");
goto error;
}
-
+
ZeroMemory(&vFormatEtc, sizeof(FORMATETC));
ZeroMemory(&vStgMedium, sizeof(STGMEDIUM));
- vFormatEtc.cfFormat = clipboard->ID_FILECONTENTS;
+ vFormatEtc.cfFormat = RegisterClipboardFormat(CFSTR_FILECONTENTS);
vFormatEtc.tymed = TYMED_ISTREAM;
vFormatEtc.dwAspect = 1;
vFormatEtc.lindex = fileContentsRequest->listIndex;
if (hRet == S_OK)
{
- if (vFormatEtc2.cfFormat == clipboard->ID_FILECONTENTS)
+ if (vFormatEtc2.cfFormat == RegisterClipboardFormat(CFSTR_FILECONTENTS))
{
hRet = IDataObject_GetData(pDataObj, &vFormatEtc, &vStgMedium);
hRet = IStream_Seek(pStreamStc, dlibMove, STREAM_SEEK_SET, &dlibNewPosition);
if (SUCCEEDED(hRet))
- {
hRet = IStream_Read(pStreamStc, pData, fileContentsRequest->cbRequested, (PULONG) &uSize);
- }
-
}
}
else
BOOL bRet;
bRet = wf_cliprdr_get_file_contents(clipboard->file_names[fileContentsRequest->listIndex], pData,
- fileContentsRequest->nPositionLow, fileContentsRequest->nPositionHigh,
- fileContentsRequest->cbRequested, &uSize);
+ fileContentsRequest->nPositionLow, fileContentsRequest->nPositionHigh,
+ fileContentsRequest->cbRequested, &uSize);
if (bRet == FALSE)
{
}
}
- IDataObject_Release(pDataObj);
+ rc = CHANNEL_RC_OK;
+
+error:
+ if (pDataObj)
+ IDataObject_Release(pDataObj);
if (uSize == 0)
{
pData = NULL;
}
- cliprdr_send_response_filecontents(clipboard, fileContentsRequest->streamId, uSize, pData);
+ sRc = cliprdr_send_response_filecontents(clipboard, fileContentsRequest->streamId,
+ uSize, pData);
free(pData);
- return CHANNEL_RC_OK;
-
-error:
- if (pData)
- {
- free(pData);
- pData = NULL;
- }
-
- if (pDataObj)
- {
- IDataObject_Release(pDataObj);
- pDataObj = NULL;
- }
-
- WLog_ERR(TAG, "filecontents: send failed response.");
- cliprdr_send_response_filecontents(clipboard, fileContentsRequest->streamId, 0, NULL);
+ if (sRc != CHANNEL_RC_OK)
+ return sRc;
- return ERROR_INTERNAL_ERROR;
+ return rc;
}
/**
*
* @return 0 on success, otherwise a Win32 error code
*/
-UINT wf_cliprdr_server_file_contents_response(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
+static UINT wf_cliprdr_server_file_contents_response(CliprdrClientContext* context,
+ const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
- wfClipboard* clipboard = (wfClipboard*) context->custom;
+ wfClipboard* clipboard;
+
+ if (!context || !fileContentsResponse)
+ return ERROR_INTERNAL_ERROR;
+
+ clipboard = (wfClipboard*) context->custom;
+
+ if (!clipboard)
+ return ERROR_INTERNAL_ERROR;
clipboard->req_fsize = fileContentsResponse->cbRequested;
clipboard->req_fdata = (char*) malloc(fileContentsResponse->cbRequested);
+ if (!clipboard->req_fdata)
+ return ERROR_INTERNAL_ERROR;
+
CopyMemory(clipboard->req_fdata, fileContentsResponse->requestedData, fileContentsResponse->cbRequested);
- SetEvent(clipboard->req_fevent);
+ if (!SetEvent(clipboard->req_fevent))
+ {
+ free (clipboard->req_fdata);
+ return ERROR_INTERNAL_ERROR;
+ }
return CHANNEL_RC_OK;
}
-void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
+BOOL wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr)
{
wfClipboard* clipboard;
rdpContext* context = (rdpContext*) wfc;
+ if (!context || !cliprdr)
+ return FALSE;
+
wfc->clipboard = (wfClipboard*) calloc(1, sizeof(wfClipboard));
if (!wfc->clipboard)
- return;
+ return FALSE;
clipboard = wfc->clipboard;
clipboard->wfc = wfc;
clipboard->context = cliprdr;
-
+
clipboard->channels = context->channels;
clipboard->sync = FALSE;
clipboard->map_size = 0;
if (!(clipboard->format_mappings = (formatMapping*) calloc(1, sizeof(formatMapping) * clipboard->map_capacity)))
- goto fail_format_mappings;
-
- clipboard->file_array_size = 32;
- if (!(clipboard->file_names = (WCHAR**) calloc(1, clipboard->file_array_size * sizeof(WCHAR*))))
- goto fail_file_names;
-
- if (!(clipboard->fileDescriptor = (FILEDESCRIPTORW**) calloc(1, clipboard->file_array_size * sizeof(FILEDESCRIPTORW*))))
- goto fail_file_descriptor;
+ goto error;
if (!(clipboard->response_data_event = CreateEvent(NULL, TRUE, FALSE, _T("response_data_event"))))
- goto fail_data_event;
+ goto error;
if (!(clipboard->req_fevent = CreateEvent(NULL, TRUE, FALSE, _T("request_filecontents_event"))))
- goto fail_filecontents_event;
-
- clipboard->ID_FILEDESCRIPTORW = RegisterClipboardFormatW(CFSTR_FILEDESCRIPTORW);
- clipboard->ID_FILECONTENTS = RegisterClipboardFormatW(CFSTR_FILECONTENTS);
- clipboard->ID_PREFERREDDROPEFFECT = RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT);
+ goto error;
if (!(clipboard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) cliprdr_thread_func, clipboard, 0, NULL)))
- goto fail_clipboard_thread;
+ goto error;
cliprdr->MonitorReady = wf_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = wf_cliprdr_server_capabilities;
cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response;
cliprdr->custom = (void*) wfc->clipboard;
- return;
-
-fail_clipboard_thread:
- CloseHandle(clipboard->req_fevent);
- clipboard->req_fevent = NULL;
-fail_filecontents_event:
- CloseHandle(clipboard->response_data_event);
- clipboard->response_data_event = NULL;
-fail_data_event:
- free(clipboard->fileDescriptor);
- clipboard->fileDescriptor = NULL;
-fail_file_descriptor:
- free(clipboard->file_names);
- clipboard->file_names = NULL;
-fail_file_names:
- free(clipboard->format_mappings);
- clipboard->format_mappings = NULL;
-fail_format_mappings:
- free(wfc->clipboard);
- wfc->clipboard = NULL;
+ return TRUE;
- return;
+error:
+ wf_cliprdr_uninit(wfc, cliprdr);
+ return FALSE;
}
-void wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr)
+BOOL wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr)
{
- wfClipboard* clipboard = wfc->clipboard;
+ wfClipboard* clipboard;
+
+ if (!wfc || !cliprdr)
+ return FALSE;
+
+ clipboard = wfc->clipboard;
+
+ if (!clipboard)
+ return FALSE;
cliprdr->custom = NULL;
if (!clipboard)
- return;
+ return FALSE;
if (clipboard->hwnd)
PostMessage(clipboard->hwnd, WM_QUIT, 0, 0);
clear_file_array(clipboard);
clear_format_map(clipboard);
- free(clipboard->file_names);
- free(clipboard->fileDescriptor);
free(clipboard->format_mappings);
free(clipboard);
+
+ return TRUE;
}