diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 708663381..18b594ed0 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -46,7 +46,7 @@ const char* const CB_MSG_TYPE_STRINGS[] = "CB_CLIP_CAPS", "CB_FILECONTENTS_REQUEST", "CB_FILECONTENTS_RESPONSE", - "CB_LOCK_CLIPDATA" + "CB_LOCK_CLIPDATA", "CB_UNLOCK_CLIPDATA" }; @@ -471,9 +471,9 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */ Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ - DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", - CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); #ifdef WITH_DEBUG_CLIPRDR + WLog_DBG(TAG, "msgType: %s (%d), msgFlags: %d dataLen: %d", + CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif @@ -910,7 +910,7 @@ UINT cliprdr_client_file_contents_response(CliprdrClientContext* context, CLIPRD if (fileContentsResponse->dwFlags & FILECONTENTS_SIZE) fileContentsResponse->cbRequested = sizeof(UINT64); - s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, + s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, fileContentsResponse->msgFlags, 4 + fileContentsResponse->cbRequested); if (!s) diff --git a/client/Windows/wf_client.h b/client/Windows/wf_client.h index 5ec8f8293..8f65c442a 100644 --- a/client/Windows/wf_client.h +++ b/client/Windows/wf_client.h @@ -137,7 +137,7 @@ struct wf_context int yCurrentScroll; int yMaxScroll; - wfClipboard* clipboard; + void* clipboard; CliprdrClientContext* cliprdr; FloatBar* floatbar; diff --git a/client/Windows/wf_cliprdr.c b/client/Windows/wf_cliprdr.c index dc1868ff0..f8f90a3a8 100644 --- a/client/Windows/wf_cliprdr.c +++ b/client/Windows/wf_cliprdr.c @@ -24,6 +24,14 @@ #include "config.h" #endif +#define CINTERFACE +#define COBJMACROS + +#include +#include +#include +#include + #include #include @@ -39,23 +47,120 @@ #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; + FILEDESCRIPTORW m_Dsc; + 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); @@ -69,18 +174,24 @@ HRESULT STDMETHODCALLTYPE CliprdrStream_QueryInterface(IStream* This, REFIID rii } } -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) @@ -94,23 +205,25 @@ ULONG STDMETHODCALLTYPE CliprdrStream_Release(IStream* This) } } -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; @@ -125,38 +238,46 @@ HRESULT STDMETHODCALLTYPE CliprdrStream_Read(IStream* This, void *pv, ULONG cb, 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) @@ -170,52 +291,72 @@ HRESULT STDMETHODCALLTYPE CliprdrStream_Seek(IStream* This, LARGE_INTEGER dlibMo 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; @@ -223,37 +364,40 @@ HRESULT STDMETHODCALLTYPE CliprdrStream_Stat(IStream* This, STATSTG* pstatstg, D 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, const FILEDESCRIPTORW *dsc) { IStream* iStream; + BOOL success = FALSE; + BOOL isDir = FALSE; CliprdrStream* instance; wfClipboard* clipboard = (wfClipboard*) pData; @@ -261,6 +405,8 @@ CliprdrStream* CliprdrStream_New(LONG index, void* pData) if (instance) { + instance->m_Dsc = *dsc; + iStream = &instance->iStream; iStream->lpVtbl = (IStreamVtbl*) calloc(1, sizeof(IStreamVtbl)); @@ -287,19 +433,35 @@ CliprdrStream* CliprdrStream_New(LONG index, void* pData) instance->m_pData = 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); - instance->m_lSize.QuadPart = *((LONGLONG*) clipboard->req_fdata); - free(clipboard->req_fdata); - } - else - { - free(instance); - instance = NULL; + if (instance->m_Dsc.dwFlags & FD_ATTRIBUTES) + { + if (instance->m_Dsc.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + isDir = TRUE; + } + + if (((instance->m_Dsc.dwFlags & FD_FILESIZE) == 0) && !isDir) { + /* get content size of this stream */ + 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 + success = TRUE; } } + if (!success) + { + CliprdrStream_Delete(instance); + instance = NULL; + } + return instance; } @@ -320,11 +482,14 @@ static int cliprdr_lookup_format(CliprdrDataObject* instance, FORMATETC* pFormat { 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; } @@ -333,9 +498,13 @@ static int cliprdr_lookup_format(CliprdrDataObject* instance, FORMATETC* pFormat 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)) { @@ -350,18 +519,24 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_QueryInterface(IDataObject* This, RE } } -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) @@ -370,33 +545,35 @@ ULONG STDMETHODCALLTYPE CliprdrDataObject_Release(IDataObject* This) 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) + FILEGROUPDESCRIPTOR *dsc; + 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 */ @@ -404,7 +581,8 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject* This, FORMATETC /* 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)); + dsc = (FILEGROUPDESCRIPTOR*) GlobalLock(clipboard->hmem); + instance->m_nStreams = dsc->cItems; GlobalUnlock(clipboard->hmem); if (instance->m_nStreams > 0) @@ -417,7 +595,9 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject* This, FORMATETC { for (i = 0; i < instance->m_nStreams; i++) { - instance->m_pStream[i] = (IStream*) CliprdrStream_New(i, clipboard); + instance->m_pStream[i] = (IStream*) CliprdrStream_New(i, clipboard, &dsc->fgd[i]); + if (!instance->m_pStream[i]) + return E_OUTOFMEMORY; } } } @@ -436,7 +616,7 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject* This, FORMATETC 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) { @@ -444,45 +624,43 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetData(IDataObject* This, FORMATETC 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; @@ -492,18 +670,23 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_GetCanonicalFormatEtc(IDataObject* T 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) @@ -517,28 +700,39 @@ HRESULT STDMETHODCALLTYPE CliprdrDataObject_EnumFormatEtc(IDataObject* This, DWO } } -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; @@ -546,50 +740,56 @@ CliprdrDataObject* CliprdrDataObject_New(FORMATETC* fmtetc, STGMEDIUM* stgmed, i instance = (CliprdrDataObject*) calloc(1, sizeof(CliprdrDataObject)); - if (instance) + if (!instance) + goto error; + + iDataObject = &instance->iDataObject; + + iDataObject->lpVtbl = (IDataObjectVtbl*) calloc(1, sizeof(IDataObjectVtbl)); + + if (!iDataObject->lpVtbl) + goto error; + + 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) { - iDataObject = &instance->iDataObject; + 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; - iDataObject->lpVtbl = (IDataObjectVtbl*) calloc(1, sizeof(IDataObjectVtbl)); - - if (iDataObject->lpVtbl) + for (i = 0; i < count; i++) { - 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; - - instance->m_pFormatEtc = (FORMATETC*) calloc(count, sizeof(FORMATETC)); - instance->m_pStgMedium = (STGMEDIUM*) calloc(count, sizeof(STGMEDIUM)); - - for (i = 0; i < count; i++) - { - instance->m_pFormatEtc[i] = fmtetc[i]; - instance->m_pStgMedium[i] = stgmed[i]; - } - } - else - { - 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) @@ -602,12 +802,10 @@ 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); } @@ -616,15 +814,15 @@ void CliprdrDataObject_Delete(CliprdrDataObject* instance) } } -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; @@ -634,7 +832,7 @@ BOOL wf_create_file_obj(wfClipboard* clipboard, IDataObject** ppDataObject) 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; @@ -644,22 +842,12 @@ BOOL wf_create_file_obj(wfClipboard* clipboard, IDataObject** ppDataObject) 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); @@ -676,13 +864,15 @@ static void cliprdr_format_deep_copy(FORMATETC* dest, FORMATETC* source) 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)) { @@ -697,18 +887,24 @@ HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_QueryInterface(IEnumFORMATETC* Th } } -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) @@ -722,12 +918,13 @@ ULONG STDMETHODCALLTYPE CliprdrEnumFORMATETC_Release(IEnumFORMATETC* This) } } -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)) @@ -741,10 +938,13 @@ HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Next(IEnumFORMATETC* This, ULONG 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; @@ -753,20 +953,23 @@ HRESULT STDMETHODCALLTYPE CliprdrEnumFORMATETC_Skip(IEnumFORMATETC* This, ULONG 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); @@ -785,50 +988,51 @@ CliprdrEnumFORMATETC* CliprdrEnumFORMATETC_New(int nFormats, FORMATETC* pFormatE CliprdrEnumFORMATETC* instance; IEnumFORMATETC* iEnumFORMATETC; - if (!pFormatEtc) + if ((nFormats != 0) && !pFormatEtc) return NULL; instance = (CliprdrEnumFORMATETC*) calloc(1, sizeof(CliprdrEnumFORMATETC)); - if (instance) + if (!instance) + goto error; + + iEnumFORMATETC = &instance->iEnumFORMATETC; + + 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) { - iEnumFORMATETC = &instance->iEnumFORMATETC; + instance->m_pFormatEtc = (FORMATETC*) calloc(nFormats, sizeof(FORMATETC)); + if (!instance->m_pFormatEtc) + goto error; - iEnumFORMATETC->lpVtbl = (IEnumFORMATETCVtbl*) calloc(1, sizeof(IEnumFORMATETCVtbl)); - - 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; - } + 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) { @@ -851,46 +1055,67 @@ void CliprdrEnumFORMATETC_Delete(CliprdrEnumFORMATETC* 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; @@ -898,14 +1123,17 @@ static UINT32 get_remote_format_id(wfClipboard* clipboard, UINT32 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; @@ -913,11 +1141,14 @@ static void map_ensure_capacity(wfClipboard* clipboard) } } -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++) @@ -932,106 +1163,123 @@ static void clear_format_map(wfClipboard* clipboard) } 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)) + if (IsClipboardFormatAvailable(CF_HDROP)) { - format = &formats[index++]; - - format->formatId = formatId; - - length = 0; - format->formatName = NULL; - - if (formatId >= CF_MAX) - { - length = GetClipboardFormatNameA(formatId, formatName, sizeof(formatName) - 1); - } - - if (length > 0) - { - format->formatName = _strdup(formatName); - } + formats[index++].formatId = RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW); + formats[index++].formatId = RegisterClipboardFormat(CFSTR_FILECONTENTS); + } + else + { + while (formatId = EnumClipboardFormats(formatId)) + formats[index++].formatId = formatId; } - CloseClipboard(); + numFormats = index; - formatList.msgFlags = 0; - formatList.numFormats = numFormats; - formatList.formats = formats; - - clipboard->context->ClientFormatList(clipboard->context, &formatList); + if (!CloseClipboard()) + { + free (formats); + return ERROR_INTERNAL_ERROR; + } for (index = 0; index < numFormats; index++) { - format = &formats[index]; - free(format->formatName); + GetClipboardFormatNameA(formats[index].formatId, formatName, sizeof(formatName)); + formats[index].formatName = _strdup(formatName); } + formatList.numFormats = numFormats; + formatList.formats = formats; + + rc = clipboard->context->ClientFormatList(clipboard->context, &formatList); + + for (index = 0; index < numFormats; index++) + 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; - formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest.msgFlags = CB_RESPONSE_OK; + if (!clipboard || !clipboard->context || + !clipboard->context->ClientFormatDataRequest) + return ERROR_INTERNAL_ERROR; 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; @@ -1040,28 +1288,34 @@ int cliprdr_send_request_filecontents(wfClipboard* clipboard, void* streamid, fileContentsRequest.nPositionHigh = positionhigh; fileContentsRequest.cbRequested = nreq; fileContentsRequest.clipDataId = 0; + fileContentsRequest.msgFlags = 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) @@ -1070,100 +1324,100 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, 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) - { - 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_RENDERFORMAT: - DEBUG_CLIPRDR("info: WM_RENDERFORMAT"); - if (cliprdr_send_data_request(clipboard, (UINT32) wParam) != 0) - { - DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); - break; - } - - if (!SetClipboardData((UINT) wParam, clipboard->hmem)) - { - DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError()); - if (clipboard->hmem) { GlobalFree(clipboard->hmem); clipboard->hmem = NULL; } - } - /* Note: GlobalFree() is not needed when success */ - break; - case WM_CLIPRDR_MESSAGE: - DEBUG_CLIPRDR("info: WM_CLIPRDR_MESSAGE"); - switch (wParam) + 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_RENDERFORMAT: + DEBUG_CLIPRDR("info: WM_RENDERFORMAT"); + if (cliprdr_send_data_request(clipboard, (UINT32) wParam) != 0) + { + DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); + break; + } + + if (!SetClipboardData((UINT) wParam, clipboard->hmem)) + { + DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError()); + + if (clipboard->hmem) { - 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; + GlobalFree(clipboard->hmem); + clipboard->hmem = NULL; + } + } + /* Note: GlobalFree() is not needed when success */ + break; - default: - 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; - 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); + 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); } return 0; @@ -1190,9 +1444,9 @@ static int create_cliprdr_window(wfClipboard* clipboard) 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) { @@ -1239,7 +1493,10 @@ static void* cliprdr_thread_func(void* arg) static void clear_file_array(wfClipboard* clipboard) { - int i; + size_t i; + + if (!clipboard) + return; /* clear file_names array */ if (clipboard->file_names) @@ -1249,6 +1506,9 @@ static void clear_file_array(wfClipboard* clipboard) free(clipboard->file_names[i]); clipboard->file_names[i] = NULL; } + + free (clipboard->file_names); + clipboard->file_names = NULL; } /* clear fileDescriptor array */ @@ -1259,48 +1519,59 @@ static void clear_file_array(wfClipboard* clipboard) 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); - - if (hFile == INVALID_HANDLE_VALUE) - { - return FALSE; - } - SetFilePointer(hFile, positionLow, (PLONG) &positionHigh, FILE_BEGIN); + hFile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + 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; - *puSize = nGet; +error: + if (!CloseHandle(hFile)) + res = FALSE; - return TRUE; + if (res) + *puSize = nGet; + + 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; @@ -1311,7 +1582,7 @@ static FILEDESCRIPTORW* wf_cliprdr_get_file_descriptor(WCHAR* file_name, int pat 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) { @@ -1336,17 +1607,21 @@ static FILEDESCRIPTORW* wf_cliprdr_get_file_descriptor(WCHAR* file_name, int pat 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; @@ -1355,32 +1630,51 @@ static void wf_cliprdr_array_ensure_capacity(wfClipboard* clipboard) 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("\\*")); @@ -1389,14 +1683,14 @@ static void wf_cliprdr_traverse_directory(wfClipboard* clipboard, WCHAR* Dir, in 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; } @@ -1408,8 +1702,10 @@ static void wf_cliprdr_traverse_directory(wfClipboard* clipboard, WCHAR* Dir, in 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 { @@ -1419,18 +1715,25 @@ static void wf_cliprdr_traverse_directory(wfClipboard* clipboard, WCHAR* Dir, in 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); @@ -1438,11 +1741,12 @@ int wf_cliprdr_send_client_capabilities(wfClipboard* clipboard) generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = CB_CAPS_VERSION_2; - generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES; + generalCapabilitySet.generalFlags = + CB_USE_LONG_FORMAT_NAMES | + CB_STREAM_FILECLIP_ENABLED | + CB_FILECLIP_NO_FILE_PATHS; - clipboard->context->ClientCapabilities(clipboard->context, &capabilities); - - return 1; + return clipboard->context->ClientCapabilities(clipboard->context, &capabilities); } /** @@ -1450,15 +1754,21 @@ int wf_cliprdr_send_client_capabilities(wfClipboard* clipboard) * * @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; - clipboard->sync = TRUE; - wf_cliprdr_send_client_capabilities(clipboard); - cliprdr_send_format_list(clipboard); + if (!context || !monitorReady) + return ERROR_INTERNAL_ERROR; - return CHANNEL_RC_OK; + clipboard->sync = TRUE; + rc = wf_cliprdr_send_client_capabilities(clipboard); + if (rc != CHANNEL_RC_OK) + return rc; + + return cliprdr_send_format_list(clipboard); } /** @@ -1466,27 +1776,31 @@ static UINT wf_cliprdr_monitor_ready(CliprdrClientContext* context, CLIPRDR_MONI * * @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; } @@ -1495,26 +1809,36 @@ static UINT wf_cliprdr_server_capabilities(CliprdrClientContext* context, CLIPRD * * @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 { @@ -1528,7 +1852,8 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR 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 { @@ -1538,14 +1863,31 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR 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 rc; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext* context, + CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +{ + (void)context; + (void)formatListResponse; + + if (formatListResponse->msgFlags != CB_RESPONSE_OK) + return E_FAIL; + return CHANNEL_RC_OK; } @@ -1554,9 +1896,12 @@ static UINT wf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR * * @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_lock_clipboard_data(CliprdrClientContext* context, + CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) { - wfClipboard* clipboard = (wfClipboard*) context->custom; + (void)context; + (void)lockClipboardData; + return CHANNEL_RC_OK; } @@ -1565,51 +1910,86 @@ static UINT wf_cliprdr_server_format_list_response(CliprdrClientContext* context * * @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_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 */ -UINT wf_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context, + CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { - wfClipboard* clipboard = (wfClipboard*) context->custom; - return CHANNEL_RC_OK; -} - -/** - * 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) -{ - 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); @@ -1619,126 +1999,77 @@ static UINT wf_cliprdr_server_format_data_request(CliprdrClientContext* context, 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; + } + + clear_file_array(clipboard); + + if (dropFiles->fWide) + { + /* dropFiles contains file names */ + for (wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles); + (len = wcslen(wFileName)) > 0; wFileName += len + 1) + { + wf_cliprdr_process_filename(clipboard, wFileName, wcslen(wFileName)); + } } else { - /* get DROPFILES struct from OLE */ - format_etc.cfFormat = CF_HDROP; - format_etc.tymed = TYMED_HGLOBAL; - format_etc.dwAspect = 1; - format_etc.lindex = -1; + char* p; - result = IDataObject_GetData(dataObj, &format_etc, &stg_medium); - - if (FAILED(result)) { - DEBUG_CLIPRDR("dataObj->GetData failed."); - } - - globlemem = (char*) GlobalLock(stg_medium.hGlobal); - - if (!globlemem) + for (p = (char*)((char*)dropFiles + dropFiles->pFiles); + (len = strlen(p)) > 0; p += len + 1, clipboard->nFiles++) { - GlobalUnlock(stg_medium.hGlobal); + int cchWideChar; + WCHAR *wFileName; - ReleaseStgMedium(&stg_medium); - clipboard->nFiles = 0; + 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); - goto exit; - } - uSize = GlobalSize(stg_medium.hGlobal); - - dropFiles = (DROPFILES*) malloc(uSize); - memcpy(dropFiles, globlemem, uSize); - - GlobalUnlock(stg_medium.hGlobal); - - ReleaseStgMedium(&stg_medium); - - clear_file_array(clipboard); - - if (dropFiles->fWide) - { - WCHAR* p; - int str_len; - int offset; - int pathLen; - - /* 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); - - if ((clipboard->fileDescriptor[clipboard->nFiles - 1]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) - { - /* this is a directory */ - wf_cliprdr_traverse_directory(clipboard, wFileName, pathLen); - } - } - } - else - { - char* p; - - for (p = (char*)((char*)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0; p += len + 1, clipboard->nFiles++) - { - int cchWideChar; - - 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); - } - } - -exit: - size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW); - buff = (char*) malloc(size); - - *((UINT32*) buff) = clipboard->nFiles; - - for (i = 0; i < clipboard->nFiles; i++) - { - if (clipboard->fileDescriptor[i]) - { - memcpy(buff + 4 + i * sizeof(FILEDESCRIPTORW), clipboard->fileDescriptor[i], sizeof(FILEDESCRIPTORW)); - } + wf_cliprdr_process_filename(clipboard, wFileName, cchWideChar); } } + GlobalUnlock(stg_medium.hGlobal); + + ReleaseStgMedium(&stg_medium); + +exit: + 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]) + groupDsc->fgd[i] = *clipboard->fileDescriptor[i]; + } + buff = groupDsc; + } IDataObject_Release(dataObj); } else @@ -1757,7 +2088,7 @@ exit: globlemem = (char*) GlobalLock(hClipdata); size = (int) GlobalSize(hClipdata); - buff = (char*) malloc(size); + buff = malloc(size); CopyMemory(buff, globlemem, size); GlobalUnlock(hClipdata); @@ -1765,17 +2096,15 @@ exit: CloseClipboard(); } - ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE)); - response.msgFlags = CB_RESPONSE_OK; 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; } /** @@ -1783,19 +2112,45 @@ exit: * * @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 (formatDataResponse->msgFlags != CB_RESPONSE_OK) + return E_FAIL; + + 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; } @@ -1805,25 +2160,35 @@ static UINT wf_cliprdr_server_format_data_response(CliprdrClientContext* context * * @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; @@ -1834,11 +2199,11 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP 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; @@ -1869,7 +2234,7 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP if (hRet == S_OK) { - if (vFormatEtc2.cfFormat == clipboard->ID_FILECONTENTS) + if (vFormatEtc2.cfFormat == RegisterClipboardFormat(CFSTR_FILECONTENTS)) { hRet = IDataObject_GetData(pDataObj, &vFormatEtc, &vStgMedium); @@ -1915,10 +2280,7 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP hRet = IStream_Seek(pStreamStc, dlibMove, STREAM_SEEK_SET, &dlibNewPosition); if (SUCCEEDED(hRet)) - { hRet = IStream_Read(pStreamStc, pData, fileContentsRequest->cbRequested, (PULONG) &uSize); - } - } } else @@ -1934,8 +2296,8 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP 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) { @@ -1946,7 +2308,11 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP } } - IDataObject_Release(pDataObj); + rc = CHANNEL_RC_OK; + +error: + if (pDataObj) + IDataObject_Release(pDataObj); if (uSize == 0) { @@ -1954,29 +2320,15 @@ UINT wf_cliprdr_server_file_contents_request(CliprdrClientContext* context, CLIP 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; + if (sRc != CHANNEL_RC_OK) + return sRc; -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); - - return ERROR_INTERNAL_ERROR; + return rc; } /** @@ -1984,33 +2336,55 @@ error: * * @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 (fileContentsResponse->msgFlags != CB_RESPONSE_OK) + return E_FAIL; + + 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; @@ -2018,27 +2392,16 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr) 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; @@ -2052,38 +2415,29 @@ void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr) cliprdr->ServerFileContentsResponse = wf_cliprdr_server_file_contents_response; cliprdr->custom = (void*) wfc->clipboard; - return; + return TRUE; -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; +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); @@ -2104,9 +2458,9 @@ void wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr) clear_file_array(clipboard); clear_format_map(clipboard); - free(clipboard->file_names); - free(clipboard->fileDescriptor); free(clipboard->format_mappings); free(clipboard); + + return TRUE; } diff --git a/client/Windows/wf_cliprdr.h b/client/Windows/wf_cliprdr.h index 4c1944e8f..69cd052b9 100644 --- a/client/Windows/wf_cliprdr.h +++ b/client/Windows/wf_cliprdr.h @@ -19,121 +19,9 @@ #ifndef __WF_CLIPRDR_H #define __WF_CLIPRDR_H -#define CINTERFACE -#define COBJMACROS - -#include -#include - -typedef struct wf_clipboard wfClipboard; - #include "wf_client.h" -#include - -#ifdef WITH_DEBUG_CLIPRDR -#define DEBUG_CLIPRDR(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__) -#else -#define DEBUG_CLIPRDR(fmt, ...) do { } while (0) -#endif - -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; - -CliprdrStream* CliprdrStream_New(LONG index, void* pData); -void CliprdrStream_Delete(CliprdrStream* instance); - -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; - -CliprdrDataObject* CliprdrDataObject_New(FORMATETC* fmtetc, STGMEDIUM* stgmed, int count, void* data); -void CliprdrDataObject_Delete(CliprdrDataObject* instance); - -struct _CliprdrEnumFORMATETC -{ - IEnumFORMATETC iEnumFORMATETC; - - LONG m_lRefCount; - LONG m_nIndex; - LONG m_nNumFormats; - FORMATETC* m_pFormatEtc; -}; -typedef struct _CliprdrEnumFORMATETC CliprdrEnumFORMATETC; - -CliprdrEnumFORMATETC* CliprdrEnumFORMATETC_New(int nFormats, FORMATETC* pFormatEtc); -void CliprdrEnumFORMATETC_Delete(CliprdrEnumFORMATETC* This); - -struct format_mapping -{ - UINT32 remote_format_id; - UINT32 local_format_id; - void* name; /* Unicode or ASCII characters with NULL terminator */ -}; -typedef struct format_mapping formatMapping; - -struct wf_clipboard -{ - wfContext* wfc; - rdpChannels* channels; - CliprdrClientContext* context; - - BOOL sync; - UINT32 capabilities; - - int map_size; - int map_capacity; - formatMapping* format_mappings; - - UINT32 requestedFormatId; - - HWND hwnd; - HANDLE hmem; - HANDLE thread; - HANDLE response_data_event; - - /* file clipping */ - CLIPFORMAT ID_FILEDESCRIPTORW; - CLIPFORMAT ID_FILECONTENTS; - CLIPFORMAT ID_PREFERREDDROPEFFECT; - - LPDATAOBJECT data_obj; - ULONG req_fsize; - char* req_fdata; - HANDLE req_fevent; - - int nFiles; - int file_array_size; - WCHAR** file_names; - FILEDESCRIPTORW** fileDescriptor; -}; - -void wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr); -void wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr); - -int cliprdr_send_data_request(wfClipboard* clipboard, UINT32 format); -int cliprdr_send_lock(wfClipboard* clipboard); -int cliprdr_send_unlock(wfClipboard* clipboard); -int cliprdr_send_request_filecontents(wfClipboard* clipboard, void* streamid, - int index, int flag, DWORD positionhigh, DWORD positionlow, ULONG request); +BOOL wf_cliprdr_init(wfContext* wfc, CliprdrClientContext* cliprdr); +BOOL wf_cliprdr_uninit(wfContext* wfc, CliprdrClientContext* cliprdr); #endif /* __WF_CLIPRDR_H */