Skip to content

Commit d91a6e3

Browse files
hideyukn88Hideyuki Nagase
andauthored
support non-ascii text in RDP clipboard (#18)
Co-authored-by: Hideyuki Nagase <hideyukn@ntdev.microsoft.com>
1 parent ddc6979 commit d91a6e3

File tree

1 file changed

+75
-10
lines changed

1 file changed

+75
-10
lines changed

libweston/backend-rdp/rdpclip.c

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static void *clipboard_process_bmp(struct rdp_clipboard_data_source *, BOOL);
7979
static void *clipboard_process_html(struct rdp_clipboard_data_source *, BOOL);
8080

8181
struct rdp_clipboard_supported_format clipboard_supported_formats[] = {
82-
{ 0, CF_TEXT, NULL, "text/plain;charset=utf-8", clipboard_process_text },
82+
{ 0, CF_UNICODETEXT, NULL, "text/plain;charset=utf-8", clipboard_process_text },
8383
{ 1, CF_DIB, NULL, "image/bmp", clipboard_process_bmp },
8484
{ 2, CF_PRIVATE_RTF, "Rich Text Format", "text/rtf", clipboard_process_text }, // same as text
8585
{ 3, CF_PRIVATE_HTML, "HTML Format", "text/html", clipboard_process_html },
@@ -152,24 +152,74 @@ clipboard_process_text(struct rdp_clipboard_data_source *source, BOOL is_send)
152152
freerdp_peer *client = (freerdp_peer*)source->context;
153153
RdpPeerContext *peerCtx = (RdpPeerContext *)client->context;
154154
struct rdp_backend *b = peerCtx->rdpBackend;
155+
struct wl_array data_contents;
156+
157+
wl_array_init(&data_contents);
155158

156159
if (!source->is_data_processed) {
157160
if (is_send) {
158-
/* Linux to Windows */
159-
assert(source->data_contents.size <= source->data_contents.alloc);
160-
assert(((char*)source->data_contents.data)[source->data_contents.size] == '\0');
161+
/* Linux to Windows (convert utf-8 to UNICODE) */
161162
/* Include terminating NULL in size */
163+
assert((source->data_contents.size + 1) <= source->data_contents.alloc);
164+
assert(((char*)source->data_contents.data)[source->data_contents.size] == '\0');
162165
source->data_contents.size++;
166+
167+
/* obtain size in UNICODE */
168+
size_t data_size = MultiByteToWideChar(CP_UTF8, 0,
169+
(char*)source->data_contents.data,
170+
source->data_contents.size,
171+
NULL, 0);
172+
if (data_size < 1)
173+
goto error_return;
174+
175+
data_size *= 2; // convert to size in bytes.
176+
if (!wl_array_add(&data_contents, data_size))
177+
goto error_return;
178+
179+
/* convert to UNICODE */
180+
size_t data_size_in_char = MultiByteToWideChar(CP_UTF8, 0,
181+
(char*)source->data_contents.data,
182+
source->data_contents.size,
183+
(LPWSTR)data_contents.data,
184+
data_size);
185+
assert(data_contents.size == (data_size_in_char * 2));
163186
} else {
164-
/* Windows to Linux */
165-
char *data = (char*)source->data_contents.data;
166-
size_t data_size = source->data_contents.size;
187+
/* Windows to Linux (UNICODE to utf-8) */
188+
LPWSTR data = (LPWSTR)source->data_contents.data;
189+
size_t data_size_in_char = source->data_contents.size / 2;
167190

168191
/* Windows's data has trailing chars, which Linux doesn't expect. */
169-
while(data_size && ((data[data_size-1] == '\0') || (data[data_size-1] == '\n')))
170-
data_size -= 1;
171-
source->data_contents.size = data_size;
192+
while(data_size_in_char &&
193+
((data[data_size_in_char-1] == L'\0') || (data[data_size_in_char-1] == L'\n')))
194+
data_size_in_char -= 1;
195+
if (!data_size_in_char)
196+
goto error_return;
197+
198+
/* obtain size in utf-8 */
199+
size_t data_size = WideCharToMultiByte(CP_UTF8, 0,
200+
(LPCWSTR)source->data_contents.data,
201+
data_size_in_char,
202+
NULL, 0,
203+
NULL, NULL);
204+
if (data_size < 1)
205+
goto error_return;
206+
207+
if (!wl_array_add(&data_contents, data_size))
208+
goto error_return;
209+
210+
/* convert to utf-8 */
211+
data_size = WideCharToMultiByte(CP_UTF8, 0,
212+
(LPCWSTR)source->data_contents.data,
213+
data_size_in_char,
214+
(char*)data_contents.data,
215+
data_size,
216+
NULL, NULL);
217+
assert(data_contents.size == data_size);
172218
}
219+
220+
/* swap the data_contents with new one */
221+
wl_array_release(&source->data_contents);
222+
source->data_contents = data_contents;
173223
source->is_data_processed = TRUE;
174224
}
175225

@@ -178,6 +228,21 @@ clipboard_process_text(struct rdp_clipboard_data_source *source, BOOL is_send)
178228
is_send ? "send" : "receive", (UINT32)source->data_contents.size);
179229

180230
return source->data_contents.data;
231+
232+
error_return:
233+
234+
source->state = RDP_CLIPBOARD_SOURCE_FAILED;
235+
rdp_debug_clipboard_error(b, "RDP %s FAILED (%p:%s): %s (%d bytes)\n",
236+
__func__, source, clipboard_data_source_state_to_string(source->state),
237+
is_send ? "send" : "receive", (UINT32)source->data_contents.size);
238+
//rdp_debug_clipboard_verbose(b, "RDP clipboard_process_html FAILED (%p): %s \n\"%s\"\n (%d bytes)\n",
239+
// source, is_send ? "send" : "receive",
240+
// (char *)source->data_contents.data,
241+
// (UINT32)source->data_contents.size);
242+
243+
wl_array_release(&data_contents);
244+
245+
return NULL;
181246
}
182247

183248
/* based off sample code at https://docs.microsoft.com/en-us/troubleshoot/cpp/add-html-code-clipboard

0 commit comments

Comments
 (0)