/[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 1163 - (show annotations)
Mon Mar 20 10:31:58 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 5618 byte(s)
Add serial numbers to protocol.

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

  ViewVC Help
Powered by ViewVC 1.1.26