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. */ }
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); }
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; }