VirtualBox

source: vbox/trunk/src/VBox/RDP/client/cliprdr.c@ 11725

Last change on this file since 11725 was 9902, checked in by vboxsync, 16 years ago

Added rdesktop 1.6.0.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.9 KB
Line 
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-2007
6
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.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include "rdesktop.h"
23
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
29
30#define CLIPRDR_REQUEST 0
31#define CLIPRDR_RESPONSE 1
32#define CLIPRDR_ERROR 2
33
34static VCHANNEL *cliprdr_channel;
35
36static uint8 *last_formats = NULL;
37static uint32 last_formats_length = 0;
38
39static void
40cliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length)
41{
42 STREAM s;
43
44 DEBUG_CLIPBOARD(("CLIPRDR send: type=%d, status=%d, length=%d\n", type, status, length));
45
46 s = channel_init(cliprdr_channel, length + 12);
47 out_uint16_le(s, type);
48 out_uint16_le(s, status);
49 out_uint32_le(s, length);
50 out_uint8p(s, data, length);
51 out_uint32(s, 0); /* pad? */
52 s_mark_end(s);
53 channel_send(s, cliprdr_channel);
54}
55
56/* Helper which announces our readiness to supply clipboard data
57 in a single format (such as CF_TEXT) to the RDP side.
58 To announce more than one format at a time, use
59 cliprdr_send_native_format_announce.
60 */
61void
62cliprdr_send_simple_native_format_announce(uint32 format)
63{
64 uint8 buffer[36];
65
66 DEBUG_CLIPBOARD(("cliprdr_send_simple_native_format_announce\n"));
67
68 buf_out_uint32(buffer, format);
69 memset(buffer + 4, 0, sizeof(buffer) - 4); /* description */
70 cliprdr_send_native_format_announce(buffer, sizeof(buffer));
71}
72
73/* Announces our readiness to supply clipboard data in multiple
74 formats, each denoted by a 36-byte format descriptor of
75 [ uint32 format + 32-byte description ].
76 */
77void
78cliprdr_send_native_format_announce(uint8 * formats_data, uint32 formats_data_length)
79{
80 DEBUG_CLIPBOARD(("cliprdr_send_native_format_announce\n"));
81
82 cliprdr_send_packet(CLIPRDR_FORMAT_ANNOUNCE, CLIPRDR_REQUEST, formats_data,
83 formats_data_length);
84
85 if (formats_data != last_formats)
86 {
87 if (last_formats)
88 xfree(last_formats);
89
90 last_formats = xmalloc(formats_data_length);
91 memcpy(last_formats, formats_data, formats_data_length);
92 last_formats_length = formats_data_length;
93 }
94}
95
96void
97cliprdr_send_data_request(uint32 format)
98{
99 uint8 buffer[4];
100
101 DEBUG_CLIPBOARD(("cliprdr_send_data_request\n"));
102 buf_out_uint32(buffer, format);
103 cliprdr_send_packet(CLIPRDR_DATA_REQUEST, CLIPRDR_REQUEST, buffer, sizeof(buffer));
104}
105
106void
107cliprdr_send_data(uint8 * data, uint32 length)
108{
109 DEBUG_CLIPBOARD(("cliprdr_send_data\n"));
110 cliprdr_send_packet(CLIPRDR_DATA_RESPONSE, CLIPRDR_RESPONSE, data, length);
111}
112
113static void
114cliprdr_process(STREAM s)
115{
116 uint16 type, status;
117 uint32 length, format;
118 uint8 *data;
119
120 in_uint16_le(s, type);
121 in_uint16_le(s, status);
122 in_uint32_le(s, length);
123 data = s->p;
124
125 DEBUG_CLIPBOARD(("CLIPRDR recv: type=%d, status=%d, length=%d\n", type, status, length));
126
127 if (status == CLIPRDR_ERROR)
128 {
129 switch (type)
130 {
131 case CLIPRDR_FORMAT_ACK:
132 /* FIXME: We seem to get this when we send an announce while the server is
133 still processing a paste. Try sending another announce. */
134 cliprdr_send_native_format_announce(last_formats,
135 last_formats_length);
136 break;
137 case CLIPRDR_DATA_RESPONSE:
138 ui_clip_request_failed();
139 break;
140 default:
141 DEBUG_CLIPBOARD(("CLIPRDR error (type=%d)\n", type));
142 }
143
144 return;
145 }
146
147 switch (type)
148 {
149 case CLIPRDR_CONNECT:
150 ui_clip_sync();
151 break;
152 case CLIPRDR_FORMAT_ANNOUNCE:
153 ui_clip_format_announce(data, length);
154 cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
155 return;
156 case CLIPRDR_FORMAT_ACK:
157 break;
158 case CLIPRDR_DATA_REQUEST:
159 in_uint32_le(s, format);
160 ui_clip_request_data(format);
161 break;
162 case CLIPRDR_DATA_RESPONSE:
163 ui_clip_handle_data(data, length);
164 break;
165 case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */
166 break;
167 default:
168 unimpl("CLIPRDR packet type %d\n", type);
169 }
170}
171
172void
173cliprdr_set_mode(const char *optarg)
174{
175 ui_clip_set_mode(optarg);
176}
177
178RD_BOOL
179cliprdr_init(void)
180{
181 cliprdr_channel =
182 channel_register("cliprdr",
183 CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
184 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL,
185 cliprdr_process);
186 return (cliprdr_channel != NULL);
187}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette