static void *cliprdr_thread_func(void *arg) { cliprdrContext *cliprdr = (cliprdrContext *)arg; BOOL mcode; MSG msg; int ret; HRESULT result; if ((ret = create_cliprdr_window(cliprdr)) != 0) { DEBUG_CLIPRDR("error: create clipboard window failed."); return NULL; } while ((mcode = GetMessage(&msg, 0, 0, 0) != 0)) { if (mcode == -1) { DEBUG_CLIPRDR("error: clipboard thread GetMessage failed."); break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } return NULL; }
static void* cliprdr_thread_func(void* arg) { int ret; MSG msg; BOOL mcode; wfClipboard* clipboard = (wfClipboard*) arg; OleInitialize(0); if ((ret = create_cliprdr_window(clipboard)) != 0) { DEBUG_CLIPRDR("error: create clipboard window failed."); return NULL; } while ((mcode = GetMessage(&msg, 0, 0, 0)) != 0) { if (mcode == -1) { DEBUG_CLIPRDR("error: clipboard thread GetMessage failed."); break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } OleUninitialize(); return NULL; }
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* s, uint16 length, uint16 flags) { int i; uint16 lengthCapability; uint16 cCapabilitiesSets; uint16 capabilitySetType; stream_read_uint16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ stream_seek_uint16(s); /* pad1 (2 bytes) */ DEBUG_CLIPRDR("cCapabilitiesSets %d", cCapabilitiesSets); for (i = 0; i < cCapabilitiesSets; i++) { stream_read_uint16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ stream_read_uint16(s, lengthCapability); /* lengthCapability (2 bytes) */ switch (capabilitySetType) { case CB_CAPSTYPE_GENERAL: cliprdr_process_general_capability(cliprdr, s); break; default: DEBUG_WARN("unknown cliprdr capability set: %d", capabilitySetType); break; } } }
static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, STREAM* s) { uint32 version; uint32 generalFlags; stream_read_uint32(s, version); /* version (4 bytes) */ stream_read_uint32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = true; if (generalFlags & CB_STREAM_FILECLIP_ENABLED) cliprdr->stream_fileclip_enabled = true; if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) cliprdr->fileclip_no_file_paths = true; if (generalFlags & CB_CAN_LOCK_CLIPDATA) cliprdr->can_lock_clipdata = true; cliprdr->received_caps = true; }
static void cliprdr_send_format_list_response(cliprdrPlugin* cliprdr) { wStream* s; DEBUG_CLIPRDR("Sending Clipboard Format List Response"); s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, CB_RESPONSE_OK, 0); cliprdr_packet_send(cliprdr, s); }
static BOOL wf_cliprdr_get_file_contents(WCHAR* file_name, BYTE* buffer, int positionLow, int positionHigh, int nRequested, unsigned int* puSize) { HANDLE hFile; DWORD nGet; 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); if (!ReadFile(hFile, buffer, nRequested, &nGet, NULL)) { DWORD err = GetLastError(); DEBUG_CLIPRDR("ReadFile failed with 0x%x.", err); } CloseHandle(hFile); *puSize = nGet; return TRUE; }
static int create_cliprdr_window(cliprdrContext *cliprdr) { WNDCLASSEX wnd_cls; ZeroMemory(&wnd_cls, sizeof(WNDCLASSEX)); wnd_cls.cbSize = sizeof(WNDCLASSEX); wnd_cls.style = CS_OWNDC; wnd_cls.lpfnWndProc = cliprdr_proc; wnd_cls.cbClsExtra = 0; wnd_cls.cbWndExtra = 0; wnd_cls.hIcon = NULL; wnd_cls.hCursor = NULL; wnd_cls.hbrBackground = NULL; wnd_cls.lpszMenuName = NULL; wnd_cls.lpszClassName = L"ClipboardHiddenMessageProcessor"; wnd_cls.hInstance = GetModuleHandle(NULL); wnd_cls.hIconSm = NULL; RegisterClassEx(&wnd_cls); cliprdr->hwndClipboard = CreateWindowEx(WS_EX_LEFT, L"ClipboardHiddenMessageProcessor", L"rdpclip", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), cliprdr); if (cliprdr->hwndClipboard == NULL) { DEBUG_CLIPRDR("error: CreateWindowEx failed with %x.", GetLastError()); return -1; } return 0; }
static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; RDP_CB_CLIP_CAPS *caps_event; Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif caps_event = (RDP_CB_CLIP_CAPS *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL); caps_event->capabilities = generalFlags; if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = TRUE; if (generalFlags & CB_STREAM_FILECLIP_ENABLED) cliprdr->stream_fileclip_enabled = TRUE; if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) cliprdr->fileclip_no_file_paths = TRUE; if (generalFlags & CB_CAN_LOCK_CLIPDATA) cliprdr->can_lock_clipdata = TRUE; cliprdr->received_caps = TRUE; svc_plugin_send_event((rdpSvcPlugin *)cliprdr, (wMessage *)caps_event); }
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16 length, UINT16 flags) { int i; UINT16 lengthCapability; UINT16 cCapabilitiesSets; UINT16 capabilitySetType; Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ DEBUG_CLIPRDR("cCapabilitiesSets %d", cCapabilitiesSets); for (i = 0; i < cCapabilitiesSets; i++) { Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ switch (capabilitySetType) { case CB_CAPSTYPE_GENERAL: cliprdr_process_general_capability(cliprdr, s); break; default: WLog_ERR(TAG, "unknown cliprdr capability set: %d", capabilitySetType); break; } } }
static void cliprdr_process_unlock_clipdata_event(cliprdrPlugin* plugin, RDP_CB_UNLOCK_CLIPDATA_EVENT* event) { wStream* s; DEBUG_CLIPRDR("Sending UnLock Request"); s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4); Stream_Write_UINT32(s, event->clipDataId); cliprdr_packet_send(plugin, s); }
static void cliprdr_process_tempdir_event(cliprdrPlugin* plugin, RDP_CB_TEMPDIR_EVENT* event) { wStream* s; DEBUG_CLIPRDR("Sending Temporary Directory."); s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520); Stream_Write(s, event->dirname, 520); cliprdr_packet_send(plugin, s); }
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event) { int i; wStream* s; DEBUG_CLIPRDR("Sending Clipboard Format List"); if (cb_event->raw_format_data) { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size); Stream_Write(s, cb_event->raw_format_data, cb_event->raw_format_data_size); } else { wStream* body = Stream_New(NULL, 64); for (i = 0; i < cb_event->num_formats; i++) { const char* name; int name_length; switch (cb_event->formats[i]) { case CB_FORMAT_HTML: name = CFSTR_HTML; name_length = sizeof(CFSTR_HTML); break; case CB_FORMAT_PNG: name = CFSTR_PNG; name_length = sizeof(CFSTR_PNG); break; case CB_FORMAT_JPEG: name = CFSTR_JPEG; name_length = sizeof(CFSTR_JPEG); break; case CB_FORMAT_GIF: name = CFSTR_GIF; name_length = sizeof(CFSTR_GIF); break; default: name = "\0\0"; name_length = 2; break; } if (!cliprdr->use_long_format_names) name_length = 32; Stream_EnsureRemainingCapacity(body, 4 + name_length); Stream_Write_UINT32(body, cb_event->formats[i]); Stream_Write(body, name, name_length); } Stream_SealLength(body); s = cliprdr_packet_new(CB_FORMAT_LIST, 0, Stream_Length(body)); Stream_Write(s, Stream_Buffer(body), Stream_Length(body)); Stream_Free(body, TRUE); } cliprdr_packet_send(cliprdr, s); }
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event) { int i; wStream* s; DEBUG_CLIPRDR("Sending Clipboard Format List"); if (cb_event->raw_format_data) { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size); stream_write(s, cb_event->raw_format_data, cb_event->raw_format_data_size); } else { wStream* body = stream_new(0); for (i = 0; i < cb_event->num_formats; i++) { const char* name; int name_length; switch (cb_event->formats[i]) { case CB_FORMAT_HTML: name = CFSTR_HTML; name_length = sizeof(CFSTR_HTML); break; case CB_FORMAT_PNG: name = CFSTR_PNG; name_length = sizeof(CFSTR_PNG); break; case CB_FORMAT_JPEG: name = CFSTR_JPEG; name_length = sizeof(CFSTR_JPEG); break; case CB_FORMAT_GIF: name = CFSTR_GIF; name_length = sizeof(CFSTR_GIF); break; default: name = "\0\0"; name_length = 2; break; } if (!cliprdr->use_long_format_names) name_length = 32; stream_extend(body, stream_get_size(body) + 4 + name_length); stream_write_UINT32(body, cb_event->formats[i]); stream_write(body, name, name_length); } s = cliprdr_packet_new(CB_FORMAT_LIST, 0, stream_get_size(body)); stream_write(s, stream_get_head(body), stream_get_size(body)); stream_free(body); } cliprdr_packet_send(cliprdr, s); }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; CLIPRDR_CAPABILITIES capabilities; CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; if (!context) { WLog_ERR(TAG, "cliprdr_get_client_interface failed!"); return ERROR_INTERNAL_ERROR; } Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (cliprdr->useLongFormatNames) cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE; if (cliprdr->streamFileClipEnabled) cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE; if (cliprdr->fileClipNoFilePaths) cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE; if (cliprdr->canLockClipData) cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; cliprdr->capabilitiesReceived = TRUE; if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } capabilities.cCapabilitiesSets = 1; capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = version; generalCapabilitySet.generalFlags = generalFlags; IFCALLRET(context->ServerCapabilities, error, context, &capabilities); if (error) WLog_ERR(TAG, "ServerCapabilities failed with error %lu!", error); return error; }
void cliprdr_process_format_data_request_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_REQUEST_EVENT* cb_event) { wStream* s; DEBUG_CLIPRDR("Sending Format Data Request"); s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4); Stream_Write_UINT32(s, cb_event->format); cliprdr_packet_send(cliprdr, s); }
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) { UINT16 msgType; UINT16 msgFlags; UINT32 dataLen; cliprdrPlugin* cliprdr = (cliprdrPlugin*) plugin; Stream_Read_UINT16(s, msgType); Stream_Read_UINT16(s, msgFlags); Stream_Read_UINT32(s, dataLen); DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); #ifdef WITH_DEBUG_CLIPRDR winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif switch (msgType) { case CB_CLIP_CAPS: cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags); break; case CB_MONITOR_READY: cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST: cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST_RESPONSE: cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_REQUEST: cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_RESPONSE: cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags); break; case CB_FILECONTENTS_REQUEST: cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags); break; case CB_FILECONTENTS_RESPONSE: cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags); break; case CB_LOCK_CLIPDATA: cliprdr_process_lock_clipdata(cliprdr, s, dataLen, msgFlags); break; case CB_UNLOCK_CLIPDATA: cliprdr_process_unlock_clipdata(cliprdr, s, dataLen, msgFlags); break; default: WLog_ERR(TAG, "unknown msgType %d", msgType); break; } }
static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s) { UINT16 msgType; UINT16 msgFlags; UINT32 dataLen; cliprdrPlugin* cliprdr = (cliprdrPlugin*) plugin; Stream_Read_UINT16(s, msgType); Stream_Read_UINT16(s, msgFlags); Stream_Read_UINT32(s, dataLen); DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); #ifdef WITH_DEBUG_CLIPRDR winpr_HexDump(Stream_Buffer(s), dataLen + 8); #endif switch (msgType) { case CB_CLIP_CAPS: cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags); break; case CB_MONITOR_READY: cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST: cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST_RESPONSE: cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_REQUEST: cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_RESPONSE: cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags); break; default: DEBUG_WARN("unknown msgType %d", msgType); break; } Stream_Free(s, TRUE); }
static void wf_cliprdr_traverse_directory(cliprdrContext *cliprdr, wchar_t *Dir, int pathLen) { WIN32_FIND_DATA FindFileData; HANDLE hFind; wchar_t DirSpec[MAX_PATH]; StringCchCopy(DirSpec,MAX_PATH,Dir); StringCchCat(DirSpec,MAX_PATH,TEXT("\\*")); hFind = FindFirstFile(DirSpec,&FindFileData); if(hFind == INVALID_HANDLE_VALUE) { DEBUG_CLIPRDR("FindFirstFile failed with 0x%x.", GetLastError()); return; } while(FindNextFile(hFind, &FindFileData)) { if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 && wcscmp(FindFileData.cFileName,L".") == 0 || wcscmp(FindFileData.cFileName,L"..") == 0) { continue; } if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) { wchar_t DirAdd[MAX_PATH]; StringCchCopy(DirAdd,MAX_PATH,Dir); StringCchCat(DirAdd,MAX_PATH,TEXT("\\")); StringCchCat(DirAdd,MAX_PATH,FindFileData.cFileName); wf_cliprdr_add_to_file_arrays(cliprdr, DirAdd, pathLen); wf_cliprdr_traverse_directory(cliprdr, DirAdd, pathLen); } else { WCHAR fileName[MAX_PATH]; StringCchCopy(fileName,MAX_PATH,Dir); StringCchCat(fileName,MAX_PATH,TEXT("\\")); StringCchCat(fileName,MAX_PATH,FindFileData.cFileName); wf_cliprdr_add_to_file_arrays(cliprdr, fileName, pathLen); } } FindClose(hFind); }
static void cliprdr_process_filecontents_request_event(cliprdrPlugin* plugin, RDP_CB_FILECONTENTS_REQUEST_EVENT* event) { wStream* s; DEBUG_CLIPRDR("Sending File Contents Request."); s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, 24); Stream_Write_UINT32(s, event->streamId); Stream_Write_UINT32(s, event->lindex); Stream_Write_UINT32(s, event->dwFlags); Stream_Write_UINT32(s, event->nPositionLow); Stream_Write_UINT32(s, event->nPositionHigh); Stream_Write_UINT32(s, event->cbRequested); //Stream_Write_UINT32(s, event->clipDataId); cliprdr_packet_send(plugin, s); }
static void cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; CliprdrClientContext* context; context = cliprdr_get_client_interface(cliprdr); Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ DEBUG_CLIPRDR("Version: %d", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif if (generalFlags & CB_USE_LONG_FORMAT_NAMES) cliprdr->use_long_format_names = TRUE; if (generalFlags & CB_STREAM_FILECLIP_ENABLED) cliprdr->stream_fileclip_enabled = TRUE; if (generalFlags & CB_FILECLIP_NO_FILE_PATHS) cliprdr->fileclip_no_file_paths = TRUE; if (generalFlags & CB_CAN_LOCK_CLIPDATA) cliprdr->can_lock_clipdata = TRUE; cliprdr->received_caps = TRUE; if (context->custom) { CLIPRDR_CAPABILITIES capabilities; CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; capabilities.cCapabilitiesSets = 1; capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = version; generalCapabilitySet.generalFlags = generalFlags; if (context->ServerCapabilities) context->ServerCapabilities(context, &capabilities); } else { RDP_CB_CLIP_CAPS* caps_event; caps_event = (RDP_CB_CLIP_CAPS*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_ClipCaps, NULL, NULL); caps_event->capabilities = generalFlags; svc_plugin_send_event((rdpSvcPlugin*) cliprdr, (wMessage*) caps_event); } }
static void cliprdr_process_receive(rdpSvcPlugin* plugin, STREAM* s) { uint16 msgType; uint16 msgFlags; uint32 dataLen; cliprdrPlugin* cliprdr = (cliprdrPlugin*) plugin; stream_read_uint16(s, msgType); stream_read_uint16(s, msgFlags); stream_read_uint32(s, dataLen); DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); switch (msgType) { case CB_CLIP_CAPS: cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags); break; case CB_MONITOR_READY: cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST: cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_LIST_RESPONSE: cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_REQUEST: cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags); break; case CB_FORMAT_DATA_RESPONSE: cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags); break; default: DEBUG_WARN("unknown msgType %d", msgType); break; } stream_free(s); }
void cliprdr_process_format_data_response_event(cliprdrPlugin* cliprdr, RDP_CB_DATA_RESPONSE_EVENT* cb_event) { wStream* s; DEBUG_CLIPRDR("Sending Format Data Response"); if (cb_event->size > 0) { s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_OK, cb_event->size); Stream_Write(s, cb_event->data, cb_event->size); } else { s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, CB_RESPONSE_FAIL, 0); } cliprdr_packet_send(cliprdr, s); }
static void cliprdr_process_filecontents_response_event(cliprdrPlugin* plugin, RDP_CB_FILECONTENTS_RESPONSE_EVENT* event) { wStream* s; DEBUG_CLIPRDR("Sending file contents response with size = %d", event->size); if (event->size > 0) { s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, CB_RESPONSE_OK, event->size + 4); Stream_Write_UINT32(s, event->streamId); Stream_Write(s, event->data, event->size); } else { s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, CB_RESPONSE_FAIL, 0); } cliprdr_packet_send(plugin, s); }
static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) { STREAM* s; uint32 flags; s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); DEBUG_CLIPRDR("Sending Capabilities"); flags = CB_USE_LONG_FORMAT_NAMES; stream_write_uint16(s, 1); /* cCapabilitiesSets */ stream_write_uint16(s, 0); /* pad1 */ stream_write_uint16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType */ stream_write_uint16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */ stream_write_uint32(s, CB_CAPS_VERSION_2); /* version */ stream_write_uint32(s, flags); /* generalFlags */ cliprdr_packet_send(cliprdr, s); }
static void cliprdr_send_clip_caps(cliprdrPlugin* cliprdr) { wStream* s; UINT32 flags; s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); DEBUG_CLIPRDR("Sending Capabilities"); flags = CB_USE_LONG_FORMAT_NAMES #ifdef _WIN32 | CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS #endif ; Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */ Stream_Write_UINT16(s, 0); /* pad1 */ Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType */ Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability */ Stream_Write_UINT32(s, CB_CAPS_VERSION_2); /* version */ Stream_Write_UINT32(s, flags); /* generalFlags */ cliprdr_packet_send(cliprdr, s); }
void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIST_EVENT* cb_event) { int i; STREAM* s; DEBUG_CLIPRDR("Sending Clipboard Format List"); if (cb_event->raw_format_data) { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, cb_event->raw_format_data_size); stream_write(s, cb_event->raw_format_data, cb_event->raw_format_data_size); } else { s = cliprdr_packet_new(CB_FORMAT_LIST, 0, 36 * cb_event->num_formats); for (i = 0; i < cb_event->num_formats; i++) { stream_write_uint32(s, cb_event->formats[i]); switch (cb_event->formats[i]) { case CB_FORMAT_HTML: memcpy(stream_get_tail(s), CFSTR_HTML, sizeof(CFSTR_HTML)); break; case CB_FORMAT_PNG: memcpy(stream_get_tail(s), CFSTR_PNG, sizeof(CFSTR_PNG)); break; case CB_FORMAT_JPEG: memcpy(stream_get_tail(s), CFSTR_JPEG, sizeof(CFSTR_JPEG)); break; case CB_FORMAT_GIF: memcpy(stream_get_tail(s), CFSTR_GIF, sizeof(CFSTR_GIF)); break; } stream_seek(s, 32); } } cliprdr_packet_send(cliprdr, s); }
static void wf_cliprdr_process_cb_format_list_event(wfContext *wfc, RDP_CB_FORMAT_LIST_EVENT *event) { cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context; UINT32 left_size = event->raw_format_data_size; int i = 0; BYTE *p; BYTE* end_mark; BOOL format_forbidden = FALSE; /* ignore the formats member in event struct, only parsing raw_format_data */ p = event->raw_format_data; end_mark = p + event->raw_format_data_size; clear_format_map(cliprdr); if ((cliprdr->capabilities & CAPS_USE_LONG_FORMAT_NAMES) != 0) { while (left_size >= 6) { formatMapping *map; BYTE* tmp; int name_len; map = &cliprdr->format_mappings[i++]; Read_UINT32(p, map->remote_format_id); map->name = NULL; /* get name_len */ for (tmp = p, name_len = 0; tmp + 1 < end_mark; tmp += 2, name_len += 2) { if (*((unsigned short*) tmp) == 0) break; } if (name_len > 0) { map->name = malloc(name_len + 2); memcpy(map->name, p, name_len + 2); map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name); } else { map->local_format_id = map->remote_format_id; } left_size -= name_len + 4 + 2; p += name_len + 2; /* p's already +4 when Read_UINT32() is called. */ cliprdr->map_size++; map_ensure_capacity(cliprdr); } } else { int k; for (k = 0; k < event->raw_format_data_size / 36; k++) { formatMapping *map; int name_len; map = &cliprdr->format_mappings[i++]; Read_UINT32(p, map->remote_format_id); map->name = NULL; if (event->raw_format_unicode) { /* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */ for (name_len = 0; name_len < 32; name_len += 2) { if (*((unsigned short*) (p + name_len)) == 0) break; } if (name_len > 0) { map->name = calloc(1, name_len + 2); memcpy(map->name, p, name_len); map->local_format_id = RegisterClipboardFormatW((LPCWSTR)map->name); } else { map->local_format_id = map->remote_format_id; } } else { /* get name_len, in bytes, if the file name is truncated, no terminated null will be included. */ for (name_len = 0; name_len < 32; name_len += 1) { if (*((unsigned char*) (p + name_len)) == 0) break; } if (name_len > 0) { map->name = calloc(1, name_len + 1); memcpy(map->name, p, name_len); map->local_format_id = RegisterClipboardFormatA((LPCSTR)map->name); } else { map->local_format_id = map->remote_format_id; } } p += 32; /* p's already +4 when Read_UINT32() is called. */ cliprdr->map_size++; map_ensure_capacity(cliprdr); } } if (!OpenClipboard(cliprdr->hwndClipboard)) { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); return; } if (!EmptyClipboard()) { DEBUG_CLIPRDR("EmptyClipboard failed with 0x%x", GetLastError()); CloseClipboard(); return; } for (i = 0; i < cliprdr->map_size; i++) { SetClipboardData(cliprdr->format_mappings[i].local_format_id, NULL); } CloseClipboard(); }
static void wf_cliprdr_process_cb_data_request_event(wfContext *wfc, RDP_CB_DATA_REQUEST_EVENT *event) { cliprdrContext *cliprdr = (cliprdrContext *)wfc->cliprdr_context; RDP_CB_DATA_RESPONSE_EVENT *responce_event; HANDLE hClipdata; int size = 0; char *buff = NULL; char *globlemem = NULL; UINT32 local_format; local_format = event->format; if (local_format == 0x9) /* FORMAT_ID_PALETTE */ { /* TODO: implement this */ DEBUG_CLIPRDR("FORMAT_ID_PALETTE is not supported yet."); } else if (local_format == 0x3) /* FORMAT_ID_MATEFILE */ { /* TODO: implement this */ DEBUG_CLIPRDR("FORMAT_ID_MATEFILE is not supported yet."); } else if (local_format == RegisterClipboardFormatW(L"FileGroupDescriptorW")) { /* TODO: implement this */ DEBUG_CLIPRDR("FileGroupDescriptorW is not supported yet."); } 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 = GlobalSize(hClipdata); buff = (char *)malloc(size); memcpy(buff, globlemem, size); GlobalUnlock(hClipdata); CloseClipboard(); } responce_event = (RDP_CB_DATA_RESPONSE_EVENT *)freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL); responce_event->data = (BYTE *)buff; responce_event->size = size; freerdp_channels_send_event(cliprdr->channels, (wMessage *) responce_event); /* Note: don't free buff here. */ }
static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { static cliprdrContext *cliprdr = NULL; switch (Msg) { case WM_CREATE: cliprdr = (cliprdrContext *)((CREATESTRUCT *)lParam)->lpCreateParams; cliprdr->hwndNextViewer = SetClipboardViewer(hWnd); if (cliprdr->hwndNextViewer == NULL && GetLastError() != 0) { DEBUG_CLIPRDR("error: SetClipboardViewer failed with 0x%0x.", GetLastError()); } cliprdr->hwndClipboard = hWnd; break; case WM_CLOSE: ChangeClipboardChain(hWnd, cliprdr->hwndNextViewer); break; case WM_CHANGECBCHAIN: if (cliprdr->hwndNextViewer == (HWND)wParam) { cliprdr->hwndNextViewer = (HWND)lParam; } else if (cliprdr->hwndNextViewer != NULL) { SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam); } break; case WM_DRAWCLIPBOARD: if (cliprdr->channel_initialized) { if (GetClipboardOwner() != cliprdr->hwndClipboard) { if (!cliprdr->hmem) { cliprdr->hmem = GlobalFree(cliprdr->hmem); } cliprdr_send_format_list(cliprdr); } } if (cliprdr->hwndNextViewer != NULL && cliprdr->hwndNextViewer != hWnd) SendMessage(cliprdr->hwndNextViewer, Msg, wParam, lParam); break; case WM_RENDERALLFORMATS: /* discard all contexts in clipboard */ if (!OpenClipboard(cliprdr->hwndClipboard)) { DEBUG_CLIPRDR("OpenClipboard failed with 0x%x", GetLastError()); break; } EmptyClipboard(); CloseClipboard(); break; case WM_RENDERFORMAT: if (cliprdr_send_data_request(cliprdr, (UINT32)wParam) != 0) { DEBUG_CLIPRDR("error: cliprdr_send_data_request failed."); break; } if (SetClipboardData(wParam, cliprdr->hmem) == NULL) { DEBUG_CLIPRDR("SetClipboardData failed with 0x%x", GetLastError()); cliprdr->hmem = GlobalFree(cliprdr->hmem); } /* Note: GlobalFree() is not needed when success */ break; case WM_CLIPBOARDUPDATE: 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; }
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); }