mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
[client,windows] clean up clipboard
This commit is contained in:
@@ -2006,6 +2006,132 @@ static BOOL wf_cliprdr_process_filename(wfClipboard* clipboard, WCHAR* wFileName
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static SSIZE_T wf_cliprdr_tryopen(wfClipboard* clipboard, UINT32 requestedFormatId, void** pData)
|
||||
{
|
||||
SSIZE_T rc = -1;
|
||||
WINPR_ASSERT(clipboard);
|
||||
WINPR_ASSERT(pData);
|
||||
|
||||
*pData = NULL;
|
||||
|
||||
/* Ignore if other app is holding the clipboard */
|
||||
if (!try_open_clipboard(clipboard->hwnd))
|
||||
return 0;
|
||||
|
||||
HANDLE hClipdata = GetClipboardData(requestedFormatId);
|
||||
|
||||
if (!hClipdata)
|
||||
goto fail;
|
||||
|
||||
char* globlemem = (char*)GlobalLock(hClipdata);
|
||||
const SSIZE_T size = GlobalSize(hClipdata);
|
||||
if (size <= 0)
|
||||
goto unlock;
|
||||
|
||||
BYTE* buff = malloc(size);
|
||||
if (buff == NULL)
|
||||
goto fail;
|
||||
CopyMemory(buff, globlemem, size);
|
||||
*pData = buff;
|
||||
rc = size;
|
||||
|
||||
unlock:
|
||||
GlobalUnlock(hClipdata);
|
||||
|
||||
fail:
|
||||
CloseClipboard();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static SSIZE_T wf_cliprdr_get_filedescriptor(wfClipboard* clipboard, void** pData)
|
||||
{
|
||||
WINPR_ASSERT(clipboard);
|
||||
WINPR_ASSERT(pData);
|
||||
|
||||
SSIZE_T rc = -1;
|
||||
LPDATAOBJECT dataObj = NULL;
|
||||
FORMATETC format_etc = { 0 };
|
||||
STGMEDIUM stg_medium = { 0 };
|
||||
|
||||
*pData = NULL;
|
||||
|
||||
HRESULT result = OleGetClipboard(&dataObj);
|
||||
if (FAILED(result))
|
||||
return -1;
|
||||
|
||||
/* 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.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
DROPFILES* dropFiles = (DROPFILES*)GlobalLock(stg_medium.hGlobal);
|
||||
|
||||
if (!dropFiles)
|
||||
{
|
||||
ReleaseStgMedium(&stg_medium);
|
||||
clipboard->nFiles = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
clear_file_array(clipboard);
|
||||
|
||||
if (dropFiles->fWide)
|
||||
{
|
||||
/* dropFiles contains file names */
|
||||
size_t len = 0;
|
||||
for (WCHAR* wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles);
|
||||
(len = wcslen(wFileName)) > 0; wFileName += len + 1)
|
||||
{
|
||||
wf_cliprdr_process_filename(clipboard, wFileName, wcslen(wFileName));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = 0;
|
||||
for (char* p = (char*)((char*)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0;
|
||||
p += len + 1, clipboard->nFiles++)
|
||||
{
|
||||
const int cchWideChar = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, NULL, 0);
|
||||
WCHAR* wFileName = (LPWSTR)calloc(cchWideChar, sizeof(WCHAR));
|
||||
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, wFileName, cchWideChar);
|
||||
wf_cliprdr_process_filename(clipboard, wFileName, cchWideChar);
|
||||
free(wFileName);
|
||||
}
|
||||
}
|
||||
|
||||
GlobalUnlock(stg_medium.hGlobal);
|
||||
ReleaseStgMedium(&stg_medium);
|
||||
exit:
|
||||
const size_t size = 4 + clipboard->nFiles * sizeof(FILEDESCRIPTORW);
|
||||
FILEGROUPDESCRIPTORW* groupDsc = (FILEGROUPDESCRIPTORW*)calloc(size, 1);
|
||||
|
||||
if (groupDsc)
|
||||
{
|
||||
groupDsc->cItems = clipboard->nFiles;
|
||||
|
||||
for (size_t i = 0; i < clipboard->nFiles; i++)
|
||||
{
|
||||
if (clipboard->fileDescriptor[i])
|
||||
groupDsc->fgd[i] = *clipboard->fileDescriptor[i];
|
||||
}
|
||||
|
||||
*pData = groupDsc;
|
||||
rc = size;
|
||||
}
|
||||
|
||||
IDataObject_Release(dataObj);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@@ -2015,137 +2141,37 @@ static UINT
|
||||
wf_cliprdr_server_format_data_request(CliprdrClientContext* context,
|
||||
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
|
||||
{
|
||||
UINT rc;
|
||||
size_t size = 0;
|
||||
void* buff = NULL;
|
||||
char* globlemem = NULL;
|
||||
HANDLE hClipdata = NULL;
|
||||
UINT32 requestedFormatId;
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response;
|
||||
wfClipboard* clipboard;
|
||||
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
|
||||
|
||||
if (!context || !formatDataRequest)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
clipboard = (wfClipboard*)context->custom;
|
||||
wfClipboard* clipboard = (wfClipboard*)context->custom;
|
||||
|
||||
if (!clipboard)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
requestedFormatId = formatDataRequest->requestedFormatId;
|
||||
const UINT32 requestedFormatId = formatDataRequest->requestedFormatId;
|
||||
|
||||
if (requestedFormatId == RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW))
|
||||
{
|
||||
size_t len;
|
||||
HRESULT result;
|
||||
LPDATAOBJECT dataObj = NULL;
|
||||
FORMATETC format_etc = { 0 };
|
||||
STGMEDIUM stg_medium = { 0 };
|
||||
DROPFILES* dropFiles = NULL;
|
||||
FILEGROUPDESCRIPTORW* groupDsc;
|
||||
result = OleGetClipboard(&dataObj);
|
||||
|
||||
if (FAILED(result))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
/* 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.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dropFiles = (DROPFILES*)GlobalLock(stg_medium.hGlobal);
|
||||
|
||||
if (!dropFiles)
|
||||
{
|
||||
GlobalUnlock(stg_medium.hGlobal);
|
||||
ReleaseStgMedium(&stg_medium);
|
||||
clipboard->nFiles = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
clear_file_array(clipboard);
|
||||
|
||||
if (dropFiles->fWide)
|
||||
{
|
||||
/* dropFiles contains file names */
|
||||
for (WCHAR* wFileName = (WCHAR*)((char*)dropFiles + dropFiles->pFiles);
|
||||
(len = wcslen(wFileName)) > 0; wFileName += len + 1)
|
||||
{
|
||||
wf_cliprdr_process_filename(clipboard, wFileName, wcslen(wFileName));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (char* p = (char*)((char*)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0;
|
||||
p += len + 1, clipboard->nFiles++)
|
||||
{
|
||||
int cchWideChar;
|
||||
WCHAR* wFileName;
|
||||
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);
|
||||
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 (size_t i = 0; i < clipboard->nFiles; i++)
|
||||
{
|
||||
if (clipboard->fileDescriptor[i])
|
||||
groupDsc->fgd[i] = *clipboard->fileDescriptor[i];
|
||||
}
|
||||
|
||||
buff = groupDsc;
|
||||
}
|
||||
|
||||
IDataObject_Release(dataObj);
|
||||
const SSIZE_T res = wf_cliprdr_get_filedescriptor(clipboard, requestedFormatId,
|
||||
&response.requestedFormatData);
|
||||
if (res > 0)
|
||||
response.common.dataLen = (UINT32)res;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore if other app is holding the clipboard */
|
||||
if (try_open_clipboard(clipboard->hwnd))
|
||||
{
|
||||
hClipdata = GetClipboardData(requestedFormatId);
|
||||
|
||||
if (!hClipdata)
|
||||
{
|
||||
CloseClipboard();
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
globlemem = (char*)GlobalLock(hClipdata);
|
||||
size = (int)GlobalSize(hClipdata);
|
||||
buff = malloc(size);
|
||||
if (buff == NULL)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
CopyMemory(buff, globlemem, size);
|
||||
GlobalUnlock(hClipdata);
|
||||
CloseClipboard();
|
||||
}
|
||||
const SSIZE_T res =
|
||||
wf_cliprdr_tryopen(clipboard, requestedFormatId, &response.requestedFormatData);
|
||||
if (res > 0)
|
||||
response.common.dataLen = (UINT32)res;
|
||||
}
|
||||
|
||||
response.common.msgFlags = CB_RESPONSE_OK;
|
||||
response.common.dataLen = size;
|
||||
response.requestedFormatData = (BYTE*)buff;
|
||||
rc = clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
|
||||
free(buff);
|
||||
|
||||
const UINT rc = clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
|
||||
free(response.requestedFormatData);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user