Added support for a new virtual channel, lspci, which makes it
possible for the remote RDP server to enumerate the local PCI devices. git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1052 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
0a716876be
commit
7b55ece8e4
@ -25,7 +25,7 @@ LDVNC = @LDVNC@
|
|||||||
VNCLINK = @VNCLINK@
|
VNCLINK = @VNCLINK@
|
||||||
SOUNDOBJ = @SOUNDOBJ@
|
SOUNDOBJ = @SOUNDOBJ@
|
||||||
|
|
||||||
RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o
|
RDPOBJ = tcp.o iso.o mcs.o secure.o licence.o rdp.o orders.o bitmap.o cache.o rdp5.o channels.o rdpdr.o serial.o printer.o disk.o parallel.o printercache.o mppc.o pstcache.o lspci.o
|
||||||
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
|
X11OBJ = rdesktop.o xwin.o xkeymap.o ewmhints.o xclip.o cliprdr.o
|
||||||
VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
|
VNCOBJ = vnc/rdp2vnc.o vnc/vnc.o vnc/xkeymap.o vnc/x11stubs.o
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ proto:
|
|||||||
bitmap.c cache.c channels.c cliprdr.c disk.c mppc.c ewmhints.c \
|
bitmap.c cache.c channels.c cliprdr.c disk.c mppc.c ewmhints.c \
|
||||||
iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
|
iso.c licence.c mcs.c orders.c parallel.c printer.c printercache.c \
|
||||||
pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c rdpsnd_oss.c \
|
pstcache.c rdesktop.c rdp5.c rdp.c rdpdr.c rdpsnd.c rdpsnd_oss.c \
|
||||||
secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c >> proto.h
|
secure.c serial.c tcp.c xclip.c xkeymap.c xwin.c lspci.c >> proto.h
|
||||||
cat proto.tail >> proto.h
|
cat proto.tail >> proto.h
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
|
||||||
#define MAX_CHANNELS 4
|
#define MAX_CHANNELS 5
|
||||||
#define CHANNEL_CHUNK_LENGTH 1600
|
#define CHANNEL_CHUNK_LENGTH 1600
|
||||||
#define CHANNEL_FLAG_FIRST 0x01
|
#define CHANNEL_FLAG_FIRST 0x01
|
||||||
#define CHANNEL_FLAG_LAST 0x02
|
#define CHANNEL_FLAG_LAST 0x02
|
||||||
|
39
doc/lspci-channel.txt
Normal file
39
doc/lspci-channel.txt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
Protocol overview
|
||||||
|
=================
|
||||||
|
|
||||||
|
The lspci virtual channel makes it possible for the remote RDP server
|
||||||
|
to enumerate the local PCI devices. The protocol on this channel is
|
||||||
|
text based and line oriented: One single line per request or
|
||||||
|
response. UNIX-style LF line breaks are used. The maximum line length
|
||||||
|
is 1023, newline included.
|
||||||
|
|
||||||
|
rdesktop acts as a server, with only one request:
|
||||||
|
|
||||||
|
LSPCI
|
||||||
|
|
||||||
|
The response is several lines with this syntax:
|
||||||
|
|
||||||
|
<class>,<vendor>,<device>,<subvendor>,<subdevice>,<revision>,<progif>
|
||||||
|
|
||||||
|
After the last line, a line with a single dot is sent.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
0300,102b,0525,102b,0338,04,00
|
||||||
|
0401,8086,24d5,1028,0174,02,8f
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
To enable to lspci virtual channel, run rdesktop with "-r lspci".
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
http://www.microsoft.com/msj/1099/terminal/terminal.aspx
|
||||||
|
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/termserv/termserv/terminal_services_virtual_channels.asp
|
||||||
|
|
@ -186,6 +186,11 @@ Redirects sound generated on the server to the client. "remote" only has
|
|||||||
any effect when you connect to the console with the -0 option. (Requires
|
any effect when you connect to the console with the -0 option. (Requires
|
||||||
Windows XP or newer).
|
Windows XP or newer).
|
||||||
.TP
|
.TP
|
||||||
|
.BR "-r lspci"
|
||||||
|
Activates the lspci channel, which allows the server to enumerate the
|
||||||
|
clients PCI devices. See the file lspci-channel.txt in the
|
||||||
|
documentation for more information.
|
||||||
|
.TP
|
||||||
.BR "-0"
|
.BR "-0"
|
||||||
Attach to the console of the server (requires Windows Server 2003
|
Attach to the console of the server (requires Windows Server 2003
|
||||||
or newer).
|
or newer).
|
||||||
|
4
proto.h
4
proto.h
@ -117,6 +117,8 @@ void hexdump(unsigned char *p, unsigned int len);
|
|||||||
char *next_arg(char *src, char needle);
|
char *next_arg(char *src, char needle);
|
||||||
void toupper_str(char *p);
|
void toupper_str(char *p);
|
||||||
BOOL str_startswith(const char *s, const char *prefix);
|
BOOL str_startswith(const char *s, const char *prefix);
|
||||||
|
BOOL str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data);
|
||||||
|
BOOL subprocess(char *const argv[], str_handle_lines_t linehandler, void *data);
|
||||||
char *l_to_a(long N, int base);
|
char *l_to_a(long N, int base);
|
||||||
int load_licence(unsigned char **data);
|
int load_licence(unsigned char **data);
|
||||||
void save_licence(unsigned char *data, int length);
|
void save_licence(unsigned char *data, int length);
|
||||||
@ -269,6 +271,8 @@ void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy);
|
|||||||
void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy);
|
void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy);
|
||||||
void ui_begin_update(void);
|
void ui_begin_update(void);
|
||||||
void ui_end_update(void);
|
void ui_end_update(void);
|
||||||
|
/* lspci.c */
|
||||||
|
BOOL lspci_init(void);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
120
rdesktop.c
120
rdesktop.c
@ -86,6 +86,7 @@ BOOL g_hide_decorations = False;
|
|||||||
BOOL g_use_rdp5 = True;
|
BOOL g_use_rdp5 = True;
|
||||||
BOOL g_console_session = False;
|
BOOL g_console_session = False;
|
||||||
BOOL g_numlock_sync = False;
|
BOOL g_numlock_sync = False;
|
||||||
|
BOOL lspci_enabled = False;
|
||||||
BOOL g_owncolmap = False;
|
BOOL g_owncolmap = False;
|
||||||
BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */
|
BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */
|
||||||
uint32 g_embed_wnd;
|
uint32 g_embed_wnd;
|
||||||
@ -679,6 +680,10 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
serial_enum_devices(&g_num_devices, optarg + 7);
|
serial_enum_devices(&g_num_devices, optarg + 7);
|
||||||
}
|
}
|
||||||
|
else if (str_startswith(optarg, "lspci"))
|
||||||
|
{
|
||||||
|
lspci_enabled = True;
|
||||||
|
}
|
||||||
else if (str_startswith(optarg, "lptport"))
|
else if (str_startswith(optarg, "lptport"))
|
||||||
{
|
{
|
||||||
parallel_enum_devices(&g_num_devices, optarg + 7);
|
parallel_enum_devices(&g_num_devices, optarg + 7);
|
||||||
@ -804,6 +809,10 @@ main(int argc, char *argv[])
|
|||||||
if (g_rdpsnd)
|
if (g_rdpsnd)
|
||||||
rdpsnd_init();
|
rdpsnd_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (lspci_enabled)
|
||||||
|
lspci_init();
|
||||||
|
|
||||||
rdpdr_init();
|
rdpdr_init();
|
||||||
|
|
||||||
while (run_count < 2 && continue_connect) /* add support for Session Directory; only reconnect once */
|
while (run_count < 2 && continue_connect) /* add support for Session Directory; only reconnect once */
|
||||||
@ -1178,6 +1187,117 @@ str_startswith(const char *s, const char *prefix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Split input into lines, and call linehandler for each
|
||||||
|
line. Incomplete lines are saved in the rest variable, which should
|
||||||
|
initially point to NULL. When linehandler returns False, stop and
|
||||||
|
return False. Otherwise, return True. */
|
||||||
|
BOOL
|
||||||
|
str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
|
||||||
|
{
|
||||||
|
char *buf, *p;
|
||||||
|
char *oldrest;
|
||||||
|
size_t inputlen;
|
||||||
|
size_t buflen;
|
||||||
|
size_t restlen = 0;
|
||||||
|
BOOL ret = True;
|
||||||
|
|
||||||
|
/* Copy data to buffer */
|
||||||
|
inputlen = strlen(input);
|
||||||
|
if (*rest)
|
||||||
|
restlen = strlen(*rest);
|
||||||
|
buflen = restlen + inputlen + 1;
|
||||||
|
buf = (char *) xmalloc(buflen);
|
||||||
|
buf[0] = '\0';
|
||||||
|
if (*rest)
|
||||||
|
STRNCPY(buf, *rest, buflen);
|
||||||
|
strncat(buf, input, inputlen);
|
||||||
|
p = buf;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char *newline = strchr(p, '\n');
|
||||||
|
if (newline)
|
||||||
|
{
|
||||||
|
*newline = '\0';
|
||||||
|
if (!linehandler(p, data))
|
||||||
|
{
|
||||||
|
p = newline + 1;
|
||||||
|
ret = False;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = newline + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save in rest */
|
||||||
|
oldrest = *rest;
|
||||||
|
restlen = buf + buflen - p;
|
||||||
|
*rest = (char *) xmalloc(restlen);
|
||||||
|
STRNCPY((*rest), p, restlen);
|
||||||
|
xfree(oldrest);
|
||||||
|
|
||||||
|
xfree(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute the program specified by argv. For each line in
|
||||||
|
stdout/stderr output, call linehandler. Returns false on failure. */
|
||||||
|
BOOL
|
||||||
|
subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
|
||||||
|
{
|
||||||
|
pid_t child;
|
||||||
|
int fd[2];
|
||||||
|
int n = 1;
|
||||||
|
char output[256];
|
||||||
|
char *rest = NULL;
|
||||||
|
|
||||||
|
if (pipe(fd) < 0)
|
||||||
|
{
|
||||||
|
perror("pipe");
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((child = fork()) < 0)
|
||||||
|
{
|
||||||
|
perror("fork");
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Child */
|
||||||
|
if (child == 0)
|
||||||
|
{
|
||||||
|
/* Close read end */
|
||||||
|
close(fd[0]);
|
||||||
|
|
||||||
|
/* Redirect stdout and stderr to pipe */
|
||||||
|
dup2(fd[1], 1);
|
||||||
|
dup2(fd[1], 2);
|
||||||
|
|
||||||
|
/* Execute */
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
perror("Error executing child");
|
||||||
|
_exit(128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parent. Close write end. */
|
||||||
|
close(fd[1]);
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
n = read(fd[0], output, 255);
|
||||||
|
output[n] = '\0';
|
||||||
|
str_handle_lines(output, &rest, linehandler, data);
|
||||||
|
}
|
||||||
|
xfree(rest);
|
||||||
|
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* not all clibs got ltoa */
|
/* not all clibs got ltoa */
|
||||||
#define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
|
#define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user