a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* -*- c-basic-offset: 8 -*-
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdesktop: A Remote Desktop Protocol client.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Protocol services - Clipboard functions
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Copyright 2003 Erik Forsberg <forsberg@cendio.se> for Cendio AB
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is free software: you can redistribute it and/or modify
a180a41bba1d50822df23fff0099e90b86638b89vboxsync it under the terms of the GNU General Public License as published by
a180a41bba1d50822df23fff0099e90b86638b89vboxsync the Free Software Foundation, either version 3 of the License, or
a180a41bba1d50822df23fff0099e90b86638b89vboxsync (at your option) any later version.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is distributed in the hope that it will be useful,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync but WITHOUT ANY WARRANTY; without even the implied warranty of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync GNU General Public License for more details.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync You should have received a copy of the GNU General Public License
a180a41bba1d50822df23fff0099e90b86638b89vboxsync along with this program. If not, see <http://www.gnu.org/licenses/>.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync*/
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync/*
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * the General Public License version 2 (GPLv2) at this time for any software where
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * a choice of GPL license versions is made available with the language indicating
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * that GPLv2 or any later version may be used, or where a choice of which version
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * of the GPL is applied is otherwise unspecified.
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync */
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#include "rdesktop.h"
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_CONNECT 1
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_FORMAT_ANNOUNCE 2
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_FORMAT_ACK 3
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_DATA_REQUEST 4
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_DATA_RESPONSE 5
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_REQUEST 0
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_RESPONSE 1
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define CLIPRDR_ERROR 2
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic VCHANNEL *cliprdr_channel;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint8 *last_formats = NULL;
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic uint32 last_formats_length = 0;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync STREAM s;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("CLIPRDR send: type=%d, status=%d, length=%d\n", type, status, length));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s = channel_init(cliprdr_channel, length + 12);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, type);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint16_le(s, status);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32_le(s, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint8p(s, data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync out_uint32(s, 0); /* pad? */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync s_mark_end(s);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync channel_send(s, cliprdr_channel);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Helper which announces our readiness to supply clipboard data
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in a single format (such as CF_TEXT) to the RDP side.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync To announce more than one format at a time, use
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_native_format_announce.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_send_simple_native_format_announce(uint32 format)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 buffer[36];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("cliprdr_send_simple_native_format_announce\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buf_out_uint32(buffer, format);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memset(buffer + 4, 0, sizeof(buffer) - 4); /* description */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_native_format_announce(buffer, sizeof(buffer));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* Announces our readiness to supply clipboard data in multiple
a180a41bba1d50822df23fff0099e90b86638b89vboxsync formats, each denoted by a 36-byte format descriptor of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync [ uint32 format + 32-byte description ].
a180a41bba1d50822df23fff0099e90b86638b89vboxsync */
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_data_length)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("cliprdr_send_native_format_announce\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_packet(CLIPRDR_FORMAT_ANNOUNCE, CLIPRDR_REQUEST, formats_data,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync formats_data_length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (formats_data != last_formats)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (last_formats)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync xfree(last_formats);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync last_formats = xmalloc(formats_data_length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync memcpy(last_formats, formats_data, formats_data_length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync last_formats_length = formats_data_length;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_send_data_request(uint32 format)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 buffer[4];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("cliprdr_send_data_request\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync buf_out_uint32(buffer, format);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_packet(CLIPRDR_DATA_REQUEST, CLIPRDR_REQUEST, buffer, sizeof(buffer));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_send_data(uint8 * data, uint32 length)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("cliprdr_send_data\n"));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_packet(CLIPRDR_DATA_RESPONSE, CLIPRDR_RESPONSE, data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncstatic void
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_process(STREAM s)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint16 type, status;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint32 length, format;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync uint8 *data;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, type);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint16_le(s, status);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync data = s->p;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type, status, length));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (status == CLIPRDR_ERROR)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync switch (type)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_FORMAT_ACK:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* FIXME: We seem to get this when we send an announce while the server is
a180a41bba1d50822df23fff0099e90b86638b89vboxsync still processing a paste. Try sending another announce. */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_native_format_announce(last_formats,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync last_formats_length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_DATA_RESPONSE:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_request_failed();
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync default:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync DEBUG_CLIPBOARD(("CLIPRDR error (type=%d)\n", type));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsync switch (type)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync {
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_CONNECT:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_sync();
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_FORMAT_ANNOUNCE:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_format_announce(data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_FORMAT_ACK:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_DATA_REQUEST:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync in_uint32_le(s, format);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_request_data(format);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case CLIPRDR_DATA_RESPONSE:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_handle_data(data, length);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync break;
a180a41bba1d50822df23fff0099e90b86638b89vboxsync default:
a180a41bba1d50822df23fff0099e90b86638b89vboxsync unimpl("CLIPRDR packet type %d\n", type);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync }
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncvoid
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_set_mode(const char *optarg)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ui_clip_set_mode(optarg);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}
a180a41bba1d50822df23fff0099e90b86638b89vboxsync
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncRD_BOOL
a180a41bba1d50822df23fff0099e90b86638b89vboxsynccliprdr_init(void)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync{
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_channel =
a180a41bba1d50822df23fff0099e90b86638b89vboxsync channel_register("cliprdr",
a180a41bba1d50822df23fff0099e90b86638b89vboxsync CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
a180a41bba1d50822df23fff0099e90b86638b89vboxsync CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync cliprdr_process);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync return (cliprdr_channel != NULL);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync}