Пример #1
0
static void wf_cliprdr_process_cb_data_request_event(wfContext* wfc, RDP_CB_DATA_REQUEST_EVENT* event)
{
	HANDLE hClipdata;
	int size = 0;
	char* buff = NULL;
	char* globlemem = NULL;
	UINT32 local_format;
	cliprdrContext* cliprdr = (cliprdrContext*) wfc->cliprdr_context;
	RDP_CB_DATA_RESPONSE_EVENT* response_event;

	local_format = event->format;

	if (local_format == FORMAT_ID_PALETTE)
	{
		/* TODO: implement this */
		DEBUG_CLIPRDR("FORMAT_ID_PALETTE is not supported yet.");
	}
	else if (local_format == FORMAT_ID_METAFILE)
	{
		/* TODO: implement this */
		DEBUG_CLIPRDR("FORMAT_ID_MATEFILE is not supported yet.");
	}
	else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW"))
	{
		HRESULT result;
		LPDATAOBJECT dataObj;
		FORMATETC format_etc;
		STGMEDIUM stg_medium;
		DROPFILES *dropFiles;

		int len;
		int i;
		wchar_t *wFileName;
		unsigned int uSize;

		DEBUG_CLIPRDR("file descriptors request.");
		result = OleGetClipboard(&dataObj);
		if (!SUCCEEDED(result))
		{
			DEBUG_CLIPRDR("OleGetClipboard failed.");
		}

		ZeroMemory(&format_etc, sizeof(FORMATETC));
		ZeroMemory(&stg_medium, sizeof(STGMEDIUM));

		/* try to get FileGroupDescriptorW struct from OLE */
		format_etc.cfFormat = local_format;
		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))
		{
			DEBUG_CLIPRDR("Got FileGroupDescriptorW.");
			globlemem = (char *)GlobalLock(stg_medium.hGlobal);
			uSize = GlobalSize(stg_medium.hGlobal);
			size = uSize;
			buff = malloc(uSize);
			memcpy(buff, globlemem, uSize);
			GlobalUnlock(stg_medium.hGlobal);

			ReleaseStgMedium(&stg_medium);

			clear_file_array(cliprdr);
		}
		else
		{
			/* get DROPFILES struct from OLE */
			format_etc.cfFormat = CF_HDROP;
			format_etc.tymed = TYMED_HGLOBAL;
			format_etc.dwAspect = 1;
			format_etc.lindex = -1;

			result = IDataObject_GetData(dataObj, &format_etc, &stg_medium);
			if (!SUCCEEDED(result)) {
				DEBUG_CLIPRDR("dataObj->GetData failed.");
			}

			globlemem = (char *)GlobalLock(stg_medium.hGlobal);

			if (globlemem == NULL)
			{
				GlobalUnlock(stg_medium.hGlobal);

				ReleaseStgMedium(&stg_medium);
				cliprdr->nFiles = 0;

				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(cliprdr);

			if (dropFiles->fWide)
			{
				wchar_t *p;
				int str_len;
				int offset;
				int pathLen;

				/* dropFiles contains file names */
				for (wFileName = (wchar_t *)((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(cliprdr, wFileName, pathLen);

					if ((cliprdr->fileDescriptor[cliprdr->nFiles - 1]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
					{
						/* this is a directory */
						wf_cliprdr_traverse_directory(cliprdr, wFileName, pathLen);
					}
				}
			}
			else
			{
				char *p;
				for (p = (char *)((char *)dropFiles + dropFiles->pFiles); (len = strlen(p)) > 0; p += len + 1, cliprdr->nFiles++)
				{
					int cchWideChar;

					cchWideChar = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, NULL, 0);
					cliprdr->file_names[cliprdr->nFiles] = (LPWSTR)malloc(cchWideChar);
					MultiByteToWideChar(CP_ACP, MB_COMPOSITE, p, len, cliprdr->file_names[cliprdr->nFiles], cchWideChar);

					if (cliprdr->nFiles == cliprdr->file_array_size)
					{
						cliprdr->file_array_size *= 2;
						cliprdr->fileDescriptor = (FILEDESCRIPTORW **)realloc(cliprdr->fileDescriptor, cliprdr->file_array_size * sizeof(FILEDESCRIPTORW *));
						cliprdr->file_names = (wchar_t **)realloc(cliprdr->file_names, cliprdr->file_array_size * sizeof(wchar_t *));
					}
				}
			}

exit:
			size = 4 + cliprdr->nFiles * sizeof(FILEDESCRIPTORW);
			buff = (char *)malloc(size);

			Write_UINT32(buff, cliprdr->nFiles);

			for (i = 0; i < cliprdr->nFiles; i++)
			{
				if (cliprdr->fileDescriptor[i])
				{
					memcpy(buff + 4 + i * sizeof(FILEDESCRIPTORW), cliprdr->fileDescriptor[i], sizeof(FILEDESCRIPTORW));
				}
			}
		}

		IDataObject_Release(dataObj);
	}
	else
	{
		if (!OpenClipboard(cliprdr->hwndClipboard))
		{
			DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
			return;
		}

		hClipdata = GetClipboardData(event->format);

		if (!hClipdata)
		{
			DEBUG_CLIPRDR("GetClipboardData failed.");
			CloseClipboard();
			return;
		}

		globlemem = (char*) GlobalLock(hClipdata);
		size = (int) GlobalSize(hClipdata);

		buff = (char*) malloc(size);
		memcpy(buff, globlemem, size);

		GlobalUnlock(hClipdata);

		CloseClipboard();
	}

	response_event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class,
			CliprdrChannel_DataResponse, NULL, NULL);

	response_event->data = (BYTE *)buff;
	response_event->size = size;

	freerdp_channels_send_event(cliprdr->channels, (wMessage*) response_event);

	/* Note: don't free buffer here. */
}
Пример #2
0
static void cliprdr_send_format_list(cliprdrContext *cliprdr)
{
	RDP_CB_FORMAT_LIST_EVENT *cliprdr_event;
	BYTE *format_data;
	int format = 0;
	int data_size;
	int format_count;
	int len = 0;
	int namelen;

	if (!OpenClipboard(cliprdr->hwndClipboard))
	{
		DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError());
		return;
	}

	format_count = CountClipboardFormats();
	data_size = format_count * (4 + MAX_PATH * 2);

	format_data = (BYTE *)calloc(1, data_size);
	assert(format_data != NULL);

	while (format = EnumClipboardFormats(format))
	{
		Write_UINT32(format_data + len, format);
		len += 4;
		if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0)
		{
			if (format >= CF_MAX)
			{
				namelen = GetClipboardFormatNameW(format, (LPWSTR)(format_data + len), MAX_PATH);
				len += namelen * sizeof(WCHAR);
			}
			len += 2;							/* end of Unicode string */
		}
		else
		{
			if (format >= CF_MAX)
			{
				static wchar_t wName[MAX_PATH] = {0};
				int wLen;

				ZeroMemory(wName, MAX_PATH*2);
				wLen = GetClipboardFormatNameW(format, wName, MAX_PATH);
				if (wLen < 16)
				{
					memcpy(format_data + len, wName, wLen * sizeof(WCHAR));
				}
				else
				{
					memcpy(format_data + len, wName, 32);	/* truncate the long name to 32 bytes */
				}
			}
			len += 32;
		}
	}

	CloseClipboard();

	cliprdr_event = (RDP_CB_FORMAT_LIST_EVENT *) freerdp_event_new(CliprdrChannel_Class,
			CliprdrChannel_FormatList, NULL, NULL);

	cliprdr_event->raw_format_data = (BYTE *)calloc(1, len);
	assert(cliprdr_event->raw_format_data != NULL);

	CopyMemory(cliprdr_event->raw_format_data, format_data, len);
	cliprdr_event->raw_format_data_size = len;

	free(format_data);

	freerdp_channels_send_event(cliprdr->channels, (wMessage *) cliprdr_event);
}
Пример #3
0
static void wf_cliprdr_process_cb_filecontents_request_event(wfContext *wfc, RDP_CB_FILECONTENTS_REQUEST_EVENT *event)
{
	cliprdrContext		*cliprdr = (cliprdrContext *)wfc->cliprdr_context;
	UINT32				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;

	pData = (BYTE *)calloc(1, event->cbRequested);
	if (!pData)
		goto error;

	hRet = OleGetClipboard(&pDataObj);
	if (!SUCCEEDED(hRet))
	{
		fprintf(stderr, "filecontents: get ole clipboard failed.\n");
		goto error;
	}
	
	ZeroMemory(&vFormatEtc, sizeof(FORMATETC));
	ZeroMemory(&vStgMedium, sizeof(STGMEDIUM));

	vFormatEtc.cfFormat = cliprdr->ID_FILECONTENTS;
	vFormatEtc.tymed = TYMED_ISTREAM;
	vFormatEtc.dwAspect = 1;
	vFormatEtc.lindex = event->lindex;
	vFormatEtc.ptd = NULL;

	if (uStreamIdStc != event->streamId || pStreamStc == NULL)
	{
		LPENUMFORMATETC pEnumFormatEtc;
		ULONG CeltFetched;

		FORMATETC vFormatEtc2;
		if (pStreamStc != NULL)
		{
			IStream_Release(pStreamStc);
			pStreamStc = NULL;
		}

		bIsStreamFile = FALSE;

		hRet = IDataObject_EnumFormatEtc(pDataObj, DATADIR_GET, &pEnumFormatEtc);
		if (hRet == S_OK)
		{
			do {
				hRet = IEnumFORMATETC_Next(pEnumFormatEtc, 1, &vFormatEtc2, &CeltFetched);
				if (hRet == S_OK)
				{
					if (vFormatEtc2.cfFormat == cliprdr->ID_FILECONTENTS)
					{
						hRet = IDataObject_GetData(pDataObj, &vFormatEtc, &vStgMedium);
						if (hRet == S_OK)
						{
							pStreamStc = vStgMedium.pstm;
							uStreamIdStc = event->streamId;
							bIsStreamFile = TRUE;
						}
						break;
					}
				}
			} while (hRet == S_OK);
		}
	}

	if (bIsStreamFile == TRUE)
	{
		if (event->dwFlags == 0x00000001)            /* FILECONTENTS_SIZE */
		{
			STATSTG vStatStg;

			ZeroMemory(&vStatStg, sizeof(STATSTG));

			hRet = IStream_Stat(pStreamStc, &vStatStg, STATFLAG_NONAME);
			if (hRet == S_OK)
			{
				Write_UINT32(pData, vStatStg.cbSize.LowPart);
				Write_UINT32(pData + 4, vStatStg.cbSize.HighPart);
				uSize = event->cbRequested;
			}
		}
		else if (event->dwFlags == 0x00000002)     /* FILECONTENTS_RANGE */
		{
			LARGE_INTEGER dlibMove;
			ULARGE_INTEGER dlibNewPosition;

			dlibMove.HighPart = event->nPositionHigh;
			dlibMove.LowPart = event->nPositionLow;

			hRet = IStream_Seek(pStreamStc, dlibMove, STREAM_SEEK_SET, &dlibNewPosition);
			if (SUCCEEDED(hRet))
			{
				hRet = IStream_Read(pStreamStc, pData, event->cbRequested, (PULONG)&uSize);
			}

		}
	}
	else // is local file
	{
		if (event->dwFlags == 0x00000001)            /* FILECONTENTS_SIZE */
		{
			Write_UINT32(pData, cliprdr->fileDescriptor[event->lindex]->nFileSizeLow);
			Write_UINT32(pData + 4, cliprdr->fileDescriptor[event->lindex]->nFileSizeHigh);
			uSize = event->cbRequested;
		}
		else if (event->dwFlags == 0x00000002)     /* FILECONTENTS_RANGE */
		{
			BOOL bRet;

			bRet = wf_cliprdr_get_file_contents(cliprdr->file_names[event->lindex], pData,
				event->nPositionLow, event->nPositionHigh, event->cbRequested, &uSize);
			if (bRet == FALSE)
			{
				fprintf(stderr, "get file contents failed.\n");
				uSize = 0;
				goto error;
			}
		}
	}

	IDataObject_Release(pDataObj);

	if (uSize == 0)
	{
		free(pData);
		pData = NULL;
	}

	cliprdr_send_response_filecontents(cliprdr, event->streamId, uSize, pData);

	return;

error:
	if (pData)
	{
		free(pData);
		pData = NULL;
	}

	if (pDataObj)
	{
		IDataObject_Release(pDataObj);
		pDataObj = NULL;
	}
	fprintf(stderr, "filecontents: send failed response.\n");
	cliprdr_send_response_filecontents(cliprdr, event->streamId, 0, NULL);
	return;
}