35 |
#define INVALID_CHARS "," |
#define INVALID_CHARS "," |
36 |
#define REPLACEMENT_CHAR '_' |
#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; |
static HANDLE g_mutex = NULL; |
54 |
static HANDLE g_vchannel = NULL; |
static HANDLE g_vchannel = NULL; |
55 |
|
|
56 |
void |
DLL_EXPORT void |
57 |
debug(char *format, ...) |
debug(char *format, ...) |
58 |
{ |
{ |
59 |
va_list argp; |
va_list argp; |
60 |
char buf[256]; |
char buf[256]; |
61 |
|
|
|
sprintf(buf, "DEBUG,"); |
|
|
|
|
62 |
va_start(argp, format); |
va_start(argp, format); |
63 |
_vsnprintf(buf + sizeof("DEBUG,") - 1, sizeof(buf) - sizeof("DEBUG,") + 1, format, argp); |
_vsnprintf(buf, sizeof(buf), format, argp); |
64 |
va_end(argp); |
va_end(argp); |
65 |
|
|
66 |
vchannel_strfilter(buf + sizeof("DEBUG,")); |
vchannel_strfilter(buf); |
67 |
|
|
68 |
vchannel_write(buf); |
vchannel_write("DEBUG", buf); |
69 |
} |
} |
70 |
|
|
71 |
#define CONVERT_BUFFER_SIZE 1024 |
#define CONVERT_BUFFER_SIZE 1024 |
72 |
static char convert_buffer[CONVERT_BUFFER_SIZE]; |
static char convert_buffer[CONVERT_BUFFER_SIZE]; |
73 |
|
|
74 |
const char * |
DLL_EXPORT const char * |
75 |
unicode_to_utf8(const unsigned short *string) |
unicode_to_utf8(const unsigned short *string) |
76 |
{ |
{ |
77 |
unsigned char *buf; |
unsigned char *buf; |
116 |
return convert_buffer; |
return convert_buffer; |
117 |
} |
} |
118 |
|
|
119 |
int |
DLL_EXPORT int |
120 |
vchannel_open() |
vchannel_open() |
121 |
{ |
{ |
122 |
g_vchannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, |
g_vchannel = WTSVirtualChannelOpen(WTS_CURRENT_SERVER_HANDLE, |
136 |
return 0; |
return 0; |
137 |
} |
} |
138 |
|
|
139 |
void |
DLL_EXPORT void |
140 |
vchannel_close() |
vchannel_close() |
141 |
{ |
{ |
142 |
if (g_mutex) |
if (g_mutex) |
149 |
g_vchannel = NULL; |
g_vchannel = NULL; |
150 |
} |
} |
151 |
|
|
152 |
int |
DLL_EXPORT int |
153 |
vchannel_is_open() |
vchannel_is_open() |
154 |
{ |
{ |
155 |
if (g_vchannel == NULL) |
if (g_vchannel == NULL) |
158 |
return 1; |
return 1; |
159 |
} |
} |
160 |
|
|
161 |
int |
DLL_EXPORT int |
162 |
vchannel_read(char *line, size_t length) |
vchannel_read(char *line, size_t length) |
163 |
{ |
{ |
164 |
static BOOL overflow_mode = FALSE; |
static BOOL overflow_mode = FALSE; |
228 |
return 0; |
return 0; |
229 |
} |
} |
230 |
|
|
231 |
int |
DLL_EXPORT int |
232 |
vchannel_write(const char *format, ...) |
vchannel_write(const char *command, const char *format, ...) |
233 |
{ |
{ |
234 |
BOOL result; |
BOOL result; |
235 |
va_list argp; |
va_list argp; |
239 |
|
|
240 |
assert(vchannel_is_open()); |
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); |
va_start(argp, format); |
249 |
size = _vsnprintf(buf, sizeof(buf), format, argp); |
size += _vsnprintf(buf + size, sizeof(buf) - size, format, argp); |
250 |
va_end(argp); |
va_end(argp); |
251 |
|
|
252 |
assert(size < sizeof(buf)); |
assert(size < sizeof(buf)); |
253 |
|
|
|
WaitForSingleObject(g_mutex, INFINITE); |
|
254 |
result = WTSVirtualChannelWrite(g_vchannel, buf, (ULONG) strlen(buf), &bytes_written); |
result = WTSVirtualChannelWrite(g_vchannel, buf, (ULONG) strlen(buf), &bytes_written); |
255 |
result = WTSVirtualChannelWrite(g_vchannel, "\n", (ULONG) 1, &bytes_written); |
result = WTSVirtualChannelWrite(g_vchannel, "\n", (ULONG) 1, &bytes_written); |
256 |
|
|
257 |
|
g_vchannel_serial++; |
258 |
|
|
259 |
ReleaseMutex(g_mutex); |
ReleaseMutex(g_mutex); |
260 |
|
|
261 |
if (!result) |
if (!result) |
264 |
return bytes_written; |
return bytes_written; |
265 |
} |
} |
266 |
|
|
267 |
void |
DLL_EXPORT void |
268 |
vchannel_block() |
vchannel_block() |
269 |
{ |
{ |
270 |
WaitForSingleObject(g_mutex, INFINITE); |
WaitForSingleObject(g_mutex, INFINITE); |
271 |
} |
} |
272 |
|
|
273 |
void |
DLL_EXPORT void |
274 |
vchannel_unblock() |
vchannel_unblock() |
275 |
{ |
{ |
276 |
ReleaseMutex(g_mutex); |
ReleaseMutex(g_mutex); |
277 |
} |
} |
278 |
|
|
279 |
const char * |
DLL_EXPORT const char * |
280 |
vchannel_strfilter(char *string) |
vchannel_strfilter(char *string) |
281 |
{ |
{ |
282 |
char *c; |
char *c; |
290 |
return string; |
return string; |
291 |
} |
} |
292 |
|
|
293 |
const char * |
DLL_EXPORT const char * |
294 |
vchannel_strfilter_unicode(const unsigned short *string) |
vchannel_strfilter_unicode(const unsigned short *string) |
295 |
{ |
{ |
296 |
return vchannel_strfilter((char *) unicode_to_utf8(string)); |
return vchannel_strfilter((char *) unicode_to_utf8(string)); |