1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Clipboard functions
4 Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5 Copyright (C) Matthew Chapman 2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #define CLIPRDR_CONNECT 1
25 #define CLIPRDR_FORMAT_ANNOUNCE 2
26 #define CLIPRDR_FORMAT_ACK 3
27 #define CLIPRDR_DATA_REQUEST 4
28 #define CLIPRDR_DATA_RESPONSE 5
30 #define CLIPRDR_REQUEST 0
31 #define CLIPRDR_RESPONSE 1
32 #define CLIPRDR_ERROR 2
35 cliprdr_send_packet(RDPCLIENT
* This
, uint16 type
, uint16 status
, uint8
* data
, uint32 length
)
39 DEBUG_CLIPBOARD(("CLIPRDR send: type=%d, status=%d, length=%d\n", type
, status
, length
));
41 s
= channel_init(This
, This
->cliprdr
.channel
, length
+ 12);
42 out_uint16_le(s
, type
);
43 out_uint16_le(s
, status
);
44 out_uint32_le(s
, length
);
45 out_uint8p(s
, data
, length
);
46 out_uint32(s
, 0); /* pad? */
48 channel_send(This
, s
, This
->cliprdr
.channel
);
51 /* Helper which announces our readiness to supply clipboard data
52 in a single format (such as CF_TEXT) to the RDP side.
53 To announce more than one format at a time, use
54 cliprdr_send_native_format_announce.
57 cliprdr_send_simple_native_format_announce(RDPCLIENT
* This
, uint32 format
)
61 DEBUG_CLIPBOARD(("cliprdr_send_simple_native_format_announce\n"));
63 buf_out_uint32(buffer
, format
);
64 memset(buffer
+ 4, 0, sizeof(buffer
) - 4); /* description */
65 cliprdr_send_native_format_announce(This
, buffer
, sizeof(buffer
));
68 /* Announces our readiness to supply clipboard data in multiple
69 formats, each denoted by a 36-byte format descriptor of
70 [ uint32 format + 32-byte description ].
73 cliprdr_send_native_format_announce(RDPCLIENT
* This
, uint8
* formats_data
, uint32 formats_data_length
)
75 DEBUG_CLIPBOARD(("cliprdr_send_native_format_announce\n"));
77 cliprdr_send_packet(This
, CLIPRDR_FORMAT_ANNOUNCE
, CLIPRDR_REQUEST
, formats_data
,
80 if (formats_data
!= This
->cliprdr
.last_formats
)
82 if (This
->cliprdr
.last_formats
)
83 xfree(This
->cliprdr
.last_formats
);
85 This
->cliprdr
.last_formats
= xmalloc(formats_data_length
);
86 memcpy(This
->cliprdr
.last_formats
, formats_data
, formats_data_length
);
87 This
->cliprdr
.last_formats_length
= formats_data_length
;
92 cliprdr_send_data_request(RDPCLIENT
* This
, uint32 format
)
96 DEBUG_CLIPBOARD(("cliprdr_send_data_request\n"));
97 buf_out_uint32(buffer
, format
);
98 cliprdr_send_packet(This
, CLIPRDR_DATA_REQUEST
, CLIPRDR_REQUEST
, buffer
, sizeof(buffer
));
102 cliprdr_send_data(RDPCLIENT
* This
, uint8
* data
, uint32 length
)
104 DEBUG_CLIPBOARD(("cliprdr_send_data\n"));
105 cliprdr_send_packet(This
, CLIPRDR_DATA_RESPONSE
, CLIPRDR_RESPONSE
, data
, length
);
109 cliprdr_process(RDPCLIENT
* This
, STREAM s
)
112 uint32 length
, format
;
115 in_uint16_le(s
, type
);
116 in_uint16_le(s
, status
);
117 in_uint32_le(s
, length
);
120 DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type
, status
, length
));
122 if (status
== CLIPRDR_ERROR
)
126 case CLIPRDR_FORMAT_ACK
:
127 /* FIXME: We seem to get this when we send an announce while the server is
128 still processing a paste. Try sending another announce. */
129 cliprdr_send_native_format_announce(This
, This
->cliprdr
.last_formats
,
130 This
->cliprdr
.last_formats_length
);
132 case CLIPRDR_DATA_RESPONSE
:
133 ui_clip_request_failed(This
);
136 DEBUG_CLIPBOARD(("CLIPRDR error (type=%d)\n", type
));
144 case CLIPRDR_CONNECT
:
147 case CLIPRDR_FORMAT_ANNOUNCE
:
148 ui_clip_format_announce(This
, data
, length
);
149 cliprdr_send_packet(This
, CLIPRDR_FORMAT_ACK
, CLIPRDR_RESPONSE
, NULL
, 0);
151 case CLIPRDR_FORMAT_ACK
:
153 case CLIPRDR_DATA_REQUEST
:
154 in_uint32_le(s
, format
);
155 ui_clip_request_data(This
, format
);
157 case CLIPRDR_DATA_RESPONSE
:
158 ui_clip_handle_data(This
, data
, length
);
160 case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */
163 unimpl("CLIPRDR packet type %d\n", type
);
168 cliprdr_set_mode(RDPCLIENT
* This
, const char *optarg
)
170 ui_clip_set_mode(This
, optarg
);
174 cliprdr_init(RDPCLIENT
* This
)
176 This
->cliprdr
.channel
=
177 channel_register(This
, "cliprdr",
178 CHANNEL_OPTION_INITIALIZED
| CHANNEL_OPTION_ENCRYPT_RDP
|
179 CHANNEL_OPTION_COMPRESS_RDP
| CHANNEL_OPTION_SHOW_PROTOCOL
,
181 return (This
->cliprdr
.channel
!= NULL
);