/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/vchannel.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/seamlessrdp/ServerExe/vchannel.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1134 - (show annotations)
Wed Mar 15 13:19:54 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 5353 byte(s)
Get window titles in unicode and send them over the channel in UTF-8. This
also meant that we had to catch WM_SETTEXT after it was handled (so that we
can use GetWindowTextW()).

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Seamless windows - Virtual channel handling
4
5 Copyright (C) Pierre Ossman <ossman@cendio.se> 2006
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 <assert.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <errno.h>
26
27 #include <windows.h>
28 #include <wtsapi32.h>
29 #include <cchannel.h>
30
31 #include "vchannel.h"
32
33 #define CHANNELNAME "seamrdp"
34
35 #define INVALID_CHARS ","
36 #define REPLACEMENT_CHAR '_'
37
38 static HANDLE g_mutex = NULL;
39 static HANDLE g_vchannel = NULL;
40
41 void
42 debug(char *format, ...)
43 {
44 va_list argp;
45 char buf[256];
46
47 sprintf(buf, "DEBUG,");
48
49 va_start(argp, format);
50 _vsnprintf(buf + sizeof("DEBUG,") - 1, sizeof(buf) - sizeof("DEBUG,") + 1, format, argp);
51 va_end(argp);
52
53 vchannel_strfilter(buf + sizeof("DEBUG,"));
54
55 vchannel_write(buf);
56 }
57
58 #define CONVERT_BUFFER_SIZE 1024
59 static char convert_buffer[CONVERT_BUFFER_SIZE];
60
61 const char *
62 unicode_to_utf8(const unsigned short *string)
63 {
64 unsigned char *buf;
65 size_t size;
66
67 buf = (unsigned char *) convert_buffer;
68 size = sizeof(convert_buffer) - 1;
69
70 /* We do not handle characters outside BMP (i.e. we can't do UTF-16) */
71 while (*string != 0x0000)
72 {
73 if (*string < 0x80)
74 {
75 if (size < 1)
76 break;
77 *buf++ = (unsigned char) *string;
78 size--;
79 }
80 else if (*string < 0x800)
81 {
82 if (size < 2)
83 break;
84 *buf++ = 0xC0 | (*string >> 6);
85 *buf++ = 0x80 | (*string & 0x3F);
86 size -= 2;
87 }
88 else if (*string < 0x10000)
89 {
90 if (size < 3)
91 break;
92 *buf++ = 0xE0 | (*string >> 12);
93 *buf++ = 0x80 | (*string >> 6 & 0x3F);
94 *buf++ = 0x80 | (*string & 0x3F);
95 size -= 2;
96 }
97 else if (*string < 0x200000)
98 {
99 if (size < 4)
100 break;
101 *buf++ = 0xF0 | (*string >> 18);
102 *buf++ = 0x80 | (*string >> 12 & 0x3F);
103 *buf++ = 0x80 | (*string >> 6 & 0x3F);
104 *buf++ = 0x80 | (*string & 0x3F);
105 size -= 2;
106 }
107
108 string++;
109 }
110
111 *buf = '\0';
112
113 return convert_buffer;
114 }
115
116 int
117 vchannel_open()
118 {
119 g_vchannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE,
120 WTS_CURRENT_SESSION, CHANNELNAME);
121
122 if (g_vchannel == NULL)
123 return -1;
124
125 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessChannel");
126 if (!g_mutex)
127 {
128 WTSVirtualChannelClose(g_vchannel);
129 g_vchannel = NULL;
130 return -1;
131 }
132
133 return 0;
134 }
135
136 void
137 vchannel_close()
138 {
139 if (g_mutex)
140 CloseHandle(g_mutex);
141
142 if (g_vchannel)
143 WTSVirtualChannelClose(g_vchannel);
144
145 g_mutex = NULL;
146 g_vchannel = NULL;
147 }
148
149 int
150 vchannel_is_open()
151 {
152 if (g_vchannel == NULL)
153 return 0;
154 else
155 return 1;
156 }
157
158 int
159 vchannel_read(char *line, size_t length)
160 {
161 static BOOL overflow_mode = FALSE;
162 static char buffer[VCHANNEL_MAX_LINE];
163 static size_t size = 0;
164
165 char *newline;
166 int line_size;
167
168 BOOL result;
169 ULONG bytes_read;
170
171 result = WTSVirtualChannelRead(g_vchannel, 0, buffer + size,
172 sizeof(buffer) - size, &bytes_read);
173
174 if (!result)
175 {
176 errno = EIO;
177 return -1;
178 }
179
180 if (overflow_mode)
181 {
182 newline = strchr(buffer, '\n');
183 if (newline && (newline - buffer) < bytes_read)
184 {
185 size = bytes_read - (newline - buffer) - 1;
186 memmove(buffer, newline + 1, size);
187 overflow_mode = FALSE;
188 }
189 }
190 else
191 size += bytes_read;
192
193 if (overflow_mode)
194 {
195 errno = -EAGAIN;
196 return -1;
197 }
198
199 newline = strchr(buffer, '\n');
200 if (!newline || (newline - buffer) >= size)
201 {
202 if (size == sizeof(buffer))
203 {
204 overflow_mode = TRUE;
205 size = 0;
206 }
207 errno = -EAGAIN;
208 return -1;
209 }
210
211 if ((newline - buffer) >= length)
212 {
213 errno = ENOMEM;
214 return -1;
215 }
216
217 *newline = '\0';
218
219 strcpy(line, buffer);
220 line_size = newline - buffer;
221
222 size -= newline - buffer + 1;
223 memmove(buffer, newline + 1, size);
224
225 return 0;
226 }
227
228 int
229 vchannel_write(const char *format, ...)
230 {
231 BOOL result;
232 va_list argp;
233 char buf[VCHANNEL_MAX_LINE];
234 int size;
235 ULONG bytes_written;
236
237 assert(vchannel_is_open());
238
239 va_start(argp, format);
240 size = _vsnprintf(buf, sizeof(buf), format, argp);
241 va_end(argp);
242
243 assert(size < sizeof(buf));
244
245 WaitForSingleObject(g_mutex, INFINITE);
246 result = WTSVirtualChannelWrite(g_vchannel, buf, (ULONG) strlen(buf), &bytes_written);
247 result = WTSVirtualChannelWrite(g_vchannel, "\n", (ULONG) 1, &bytes_written);
248 ReleaseMutex(g_mutex);
249
250 if (!result)
251 return -1;
252
253 return bytes_written;
254 }
255
256 void
257 vchannel_block()
258 {
259 WaitForSingleObject(g_mutex, INFINITE);
260 }
261
262 void
263 vchannel_unblock()
264 {
265 ReleaseMutex(g_mutex);
266 }
267
268 const char *
269 vchannel_strfilter(char *string)
270 {
271 char *c;
272
273 for (c = string; *c != '\0'; c++)
274 {
275 if (((unsigned char) *c < 0x20) || (strchr(INVALID_CHARS, *c) != NULL))
276 *c = REPLACEMENT_CHAR;
277 }
278
279 return string;
280 }
281
282 const char *
283 vchannel_strfilter_unicode(const unsigned short *string)
284 {
285 return vchannel_strfilter((char *) unicode_to_utf8(string));
286 }

  ViewVC Help
Powered by ViewVC 1.1.26