[client,windows] clean up clipboard

This commit is contained in:
Armin Novak
2024-04-03 08:53:20 +02:00
committed by akallabeth
parent be50010d1d
commit ff92ef4331

View File

@@ -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;
}