Package: rdesktop
Version: 1.8.3-1
Severity: important
Tags: patch

RDP needs the following fixes to work well connecting to Windows 10

1) Support passing DPI to Windows 10 RDP Server; Windows 10 lost support
for using the registry provided value in this case.

2) Support using the desktop manager provided cursor instead of the remote
machine cursor; in some determinstic scenarios the remote cursor is no good,
but this is borderline impossible to detect. The user will know what to do.

-- System Information:
Debian Release: 8.6
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL 
set to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)

Versions of packages rdesktop depends on:
ii  libasound2    1.0.28-1
ii  libc6         2.19-18+deb8u6
ii  libgssglue1   0.4-2
ii  libpcsclite1  1.8.13-1
ii  libssl1.0.0   1.0.1t-1+deb8u5
ii  libx11-6      2:1.6.2-3
ii  libxrandr2    2:1.4.2-1+b1

rdesktop recommends no packages.

Versions of packages rdesktop suggests:
pn  pcscd  <none>

-- no debconf information
diff -ru stock/rdesktop-1.8.3/doc/rdesktop.1 work/rdesktop-1.8.3/doc/rdesktop.1
--- stock/rdesktop-1.8.3/doc/rdesktop.1	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/doc/rdesktop.1	2016-10-01 13:47:33.913176792 -0700
@@ -63,15 +63,18 @@
 so its use is discouraged.
 .TP
 .BR "-g <geometry>"
-Desktop geometry (WxH). If geometry is the special word "workarea", the geometry
-will be fetched from the extended window manager hints property _NET_WORKAREA, from
-the root window. The geometry can also be specified as a percentage of the whole
-screen, e.g. "-g 80%". 
-
+Desktop geometry (WxH[@DPI][+X[+Y]]). If geometry is the special word
+"workarea", the geometry will be fetched from the extended window
+manager hints property _NET_WORKAREA, from the root window. The geometry
+can also be specified as a percentage of the whole screen, e.g. "-g 80%". 
 If the specified geometry depends on the screen size, and the screen
 size is changed, rdesktop will automatically reconnect using the new
 screen size. This requires that rdesktop has been compiled with RandR
 support.
+
+The optional DPI parameter should be specified if the screen rdesktop
+is being displayed on is too far from 96 DPI for unscaled Windows to
+be readable. Windows currently accepts values from 96 to 480.
 .TP
 .BR "-i"
 Use password as smartcard pin. If a valid user certificate is matched in smart card
@@ -123,6 +126,11 @@
 Do not send mouse motion events.  This saves bandwidth, although some Windows
 applications may rely on receiving mouse motion.
 .TP
+.BR "-M"
+Use the local X cursor rather than the one from the remote machine. This is most
+useful with "-m" but has other uses. If running with no window manager, use
+xsetroot(1) to set a useful cursor first.
+.TP
 .BR "-C"
 Use private colourmap.  This will improve colour accuracy on an 8-bit display,
 but rdesktop will appear in false colour when not focused.
diff -ru stock/rdesktop-1.8.3/rdesktop.c work/rdesktop-1.8.3/rdesktop.c
--- stock/rdesktop-1.8.3/rdesktop.c	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/rdesktop.c	2016-10-01 13:41:59.146946782 -0700
@@ -72,6 +72,7 @@
 				   requested. If 1, the geometry will be fetched
 				   from _NET_WORKAREA. If negative, absolute value
 				   specifies the percent of the whole screen. */
+int g_dpi = 0;			/* device DPI: default not set */
 int g_width = 800;
 int g_height = 600;
 int g_xpos = 0;
@@ -97,6 +98,7 @@
 RD_BOOL g_polygon_ellipse_orders = True;	/* polygon / ellipse orders */
 RD_BOOL g_fullscreen = False;
 RD_BOOL g_grab_keyboard = True;
+RD_BOOL g_local_cursor = False;
 RD_BOOL g_hide_decorations = False;
 RDP_VERSION g_rdp_version = RDP_V5;	/* Default to version 5 */
 RD_BOOL g_rdpclip = True;
@@ -190,7 +192,7 @@
 	fprintf(stderr, "   -p: password (- to prompt)\n");
 	fprintf(stderr, "   -n: client hostname\n");
 	fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
-	fprintf(stderr, "   -g: desktop geometry (WxH)\n");
+	fprintf(stderr, "   -g: desktop geometry (WxH[@dpi])\n");
 #ifdef WITH_SCARD
 	fprintf(stderr, "   -i: enables smartcard authentication, password is used as pin\n");
 #endif
@@ -204,6 +206,7 @@
 	fprintf(stderr, "   -e: disable encryption (French TS)\n");
 	fprintf(stderr, "   -E: disable encryption from client to server\n");
 	fprintf(stderr, "   -m: do not send motion events\n");
+	fprintf(stderr, "   -M: use local mouse cursor\n");
 	fprintf(stderr, "   -C: use private colour map\n");
 	fprintf(stderr, "   -D: hide window manager decorations\n");
 	fprintf(stderr, "   -K: keep window manager key bindings\n");
@@ -579,7 +582,7 @@
 #define VNCOPT
 #endif
 	while ((c = getopt(argc, argv,
-			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
+			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmMzCDKS:T:NX:a:x:Pr:045h?")) != -1)
 	{
 		switch (c)
 		{
@@ -694,6 +697,16 @@
 					p++;
 				}
 
+				if (*p == '@')
+				{
+					g_dpi = strtol(p + 1, &p, 10);
+					if (g_dpi <= 0)
+					{
+						error("invalid geometry\n");
+						return EX_USAGE;
+					}
+				}
+
 				if (*p == '+' || *p == '-')
 				{
 					g_pos |= (*p == '-') ? 2 : 1;
@@ -731,6 +744,8 @@
 			case 'm':
 				g_sendmotion = False;
 				break;
+			case 'M':
+				g_local_cursor = True;
 
 			case 'C':
 				g_owncolmap = True;
diff -ru stock/rdesktop-1.8.3/secure.c work/rdesktop-1.8.3/secure.c
--- stock/rdesktop-1.8.3/secure.c	2014-02-07 00:44:55.000000000 -0800
+++ work/rdesktop-1.8.3/secure.c	2016-10-01 13:41:08.555214273 -0700
@@ -24,6 +24,7 @@
 extern char g_hostname[16];
 extern int g_width;
 extern int g_height;
+extern int g_dpi;
 extern unsigned int g_keylayout;
 extern int g_keyboard_type;
 extern int g_keyboard_subtype;
@@ -395,7 +396,7 @@
 sec_out_mcs_data(STREAM s, uint32 selected_protocol)
 {
 	int hostlen = 2 * strlen(g_hostname);
-	int length = 162 + 76 + 12 + 4;
+	int length = 162 + 76 + 12 + 4 + (g_dpi > 0 ? 18 : 0);
 	unsigned int i;
 
 	if (g_num_channels > 0)
@@ -423,7 +424,7 @@
 
 	/* Client information */
 	out_uint16_le(s, SEC_TAG_CLI_INFO);
-	out_uint16_le(s, 216);	/* length */
+	out_uint16_le(s, 216 + (g_dpi > 0 ? 18 : 0));	/* length */
 	out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 4 : 1);	/* RDP version. 1 == RDP4, 4 >= RDP5 to RDP8 */
 	out_uint16_le(s, 8);
 	out_uint16_le(s, g_width);
@@ -444,15 +445,25 @@
 	out_uint32_le(s, g_keyboard_functionkeys);
 	out_uint8s(s, 64);	/* reserved? 4 + 12 doublewords */
 	out_uint16_le(s, 0xca01);	/* colour depth? */
-	out_uint16_le(s, 1);
+	out_uint16_le(s, 1);		/* product id */
 
-	out_uint32(s, 0);
-	out_uint8(s, g_server_depth);
-	out_uint16_le(s, 0x0700);
+	out_uint32(s, 0);		/* serial number */
+	out_uint8(s, g_server_depth);	/* this stuff is misaligned should be 2,2,2,64,1,1 */
+	out_uint16_le(s, 0x0700);	/* this strange constant is split across fields */
 	out_uint8(s, 0);
 	out_uint32_le(s, 1);
 	out_uint8s(s, 64);
 	out_uint32_le(s, selected_protocol);	/* End of client info */
+	if (g_dpi > 0)
+	{
+		/* Extended client info describing monitor geometry */
+		out_uint32_le(s, g_width * 100 / (g_dpi * 254)); /* desktop physical width */
+		out_uint32_le(s, g_height * 100 / (g_dpi * 254)); /* desktop physical height */
+		out_uint16_le(s, 0); /* orientation: portrait */
+		out_uint32_le(s, g_dpi < 96 ? 100 : (g_dpi * 100 + 48) / 96); /* desktop scale factor */
+		out_uint32_le(s, g_dpi < 134 ? 100 : (g_dpi < 173 ? 140 : 180)); /* device scale factor */
+		/* the only allowed values for device scale factor are 100, 140, and 180. */
+	}
 
 	/* Write a Client Cluster Data (TS_UD_CS_CLUSTER) */
 	uint32 cluster_flags = 0;
@@ -901,7 +912,7 @@
 		return False;
 
 	/* We exchange some RDP data during the MCS-Connect */
-	mcs_data.size = 512;
+	mcs_data.size = 542;
 	mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
 	sec_out_mcs_data(&mcs_data, selected_proto);
 
diff -ru stock/rdesktop-1.8.3/xwin.c work/rdesktop-1.8.3/xwin.c
--- stock/rdesktop-1.8.3/xwin.c	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/xwin.c	2016-10-01 13:41:08.555214273 -0700
@@ -3097,9 +3097,13 @@
 void
 ui_set_cursor(RD_HCURSOR cursor)
 {
-	g_current_cursor = (Cursor) cursor;
-	XDefineCursor(g_display, g_wnd, g_current_cursor);
-	ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
+	extern RD_BOOL g_local_cursor;
+	if (!g_local_cursor)
+	{
+		g_current_cursor = (Cursor) cursor;
+		XDefineCursor(g_display, g_wnd, g_current_cursor);
+		ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
+	}
 }
 
 void
diff -ru stock/rdesktop-1.8.3/doc/rdesktop.1 work/rdesktop-1.8.3/doc/rdesktop.1
--- stock/rdesktop-1.8.3/doc/rdesktop.1	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/doc/rdesktop.1	2016-10-01 13:47:33.913176792 -0700
@@ -63,15 +63,18 @@
 so its use is discouraged.
 .TP
 .BR "-g <geometry>"
-Desktop geometry (WxH). If geometry is the special word "workarea", the geometry
-will be fetched from the extended window manager hints property _NET_WORKAREA, from
-the root window. The geometry can also be specified as a percentage of the whole
-screen, e.g. "-g 80%". 
-
+Desktop geometry (WxH[@DPI][+X[+Y]]). If geometry is the special word
+"workarea", the geometry will be fetched from the extended window
+manager hints property _NET_WORKAREA, from the root window. The geometry
+can also be specified as a percentage of the whole screen, e.g. "-g 80%". 
 If the specified geometry depends on the screen size, and the screen
 size is changed, rdesktop will automatically reconnect using the new
 screen size. This requires that rdesktop has been compiled with RandR
 support.
+
+The optional DPI parameter should be specified if the screen rdesktop
+is being displayed on is too far from 96 DPI for unscaled Windows to
+be readable. Windows currently accepts values from 96 to 480.
 .TP
 .BR "-i"
 Use password as smartcard pin. If a valid user certificate is matched in smart card
@@ -123,6 +126,11 @@
 Do not send mouse motion events.  This saves bandwidth, although some Windows
 applications may rely on receiving mouse motion.
 .TP
+.BR "-M"
+Use the local X cursor rather than the one from the remote machine. This is most
+useful with "-m" but has other uses. If running with no window manager, use
+xsetroot(1) to set a useful cursor first.
+.TP
 .BR "-C"
 Use private colourmap.  This will improve colour accuracy on an 8-bit display,
 but rdesktop will appear in false colour when not focused.
diff -ru stock/rdesktop-1.8.3/rdesktop.c work/rdesktop-1.8.3/rdesktop.c
--- stock/rdesktop-1.8.3/rdesktop.c	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/rdesktop.c	2016-10-01 13:41:59.146946782 -0700
@@ -72,6 +72,7 @@
 				   requested. If 1, the geometry will be fetched
 				   from _NET_WORKAREA. If negative, absolute value
 				   specifies the percent of the whole screen. */
+int g_dpi = 0;			/* device DPI: default not set */
 int g_width = 800;
 int g_height = 600;
 int g_xpos = 0;
@@ -97,6 +98,7 @@
 RD_BOOL g_polygon_ellipse_orders = True;	/* polygon / ellipse orders */
 RD_BOOL g_fullscreen = False;
 RD_BOOL g_grab_keyboard = True;
+RD_BOOL g_local_cursor = False;
 RD_BOOL g_hide_decorations = False;
 RDP_VERSION g_rdp_version = RDP_V5;	/* Default to version 5 */
 RD_BOOL g_rdpclip = True;
@@ -190,7 +192,7 @@
 	fprintf(stderr, "   -p: password (- to prompt)\n");
 	fprintf(stderr, "   -n: client hostname\n");
 	fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
-	fprintf(stderr, "   -g: desktop geometry (WxH)\n");
+	fprintf(stderr, "   -g: desktop geometry (WxH[@dpi])\n");
 #ifdef WITH_SCARD
 	fprintf(stderr, "   -i: enables smartcard authentication, password is used as pin\n");
 #endif
@@ -204,6 +206,7 @@
 	fprintf(stderr, "   -e: disable encryption (French TS)\n");
 	fprintf(stderr, "   -E: disable encryption from client to server\n");
 	fprintf(stderr, "   -m: do not send motion events\n");
+	fprintf(stderr, "   -M: use local mouse cursor\n");
 	fprintf(stderr, "   -C: use private colour map\n");
 	fprintf(stderr, "   -D: hide window manager decorations\n");
 	fprintf(stderr, "   -K: keep window manager key bindings\n");
@@ -579,7 +582,7 @@
 #define VNCOPT
 #endif
 	while ((c = getopt(argc, argv,
-			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
+			   VNCOPT "A:u:L:d:s:c:p:n:k:g:o:fbBeEitmMzCDKS:T:NX:a:x:Pr:045h?")) != -1)
 	{
 		switch (c)
 		{
@@ -694,6 +697,16 @@
 					p++;
 				}
 
+				if (*p == '@')
+				{
+					g_dpi = strtol(p + 1, &p, 10);
+					if (g_dpi <= 0)
+					{
+						error("invalid geometry\n");
+						return EX_USAGE;
+					}
+				}
+
 				if (*p == '+' || *p == '-')
 				{
 					g_pos |= (*p == '-') ? 2 : 1;
@@ -731,6 +744,8 @@
 			case 'm':
 				g_sendmotion = False;
 				break;
+			case 'M':
+				g_local_cursor = True;
 
 			case 'C':
 				g_owncolmap = True;
diff -ru stock/rdesktop-1.8.3/secure.c work/rdesktop-1.8.3/secure.c
--- stock/rdesktop-1.8.3/secure.c	2014-02-07 00:44:55.000000000 -0800
+++ work/rdesktop-1.8.3/secure.c	2016-10-01 13:41:08.555214273 -0700
@@ -24,6 +24,7 @@
 extern char g_hostname[16];
 extern int g_width;
 extern int g_height;
+extern int g_dpi;
 extern unsigned int g_keylayout;
 extern int g_keyboard_type;
 extern int g_keyboard_subtype;
@@ -395,7 +396,7 @@
 sec_out_mcs_data(STREAM s, uint32 selected_protocol)
 {
 	int hostlen = 2 * strlen(g_hostname);
-	int length = 162 + 76 + 12 + 4;
+	int length = 162 + 76 + 12 + 4 + (g_dpi > 0 ? 18 : 0);
 	unsigned int i;
 
 	if (g_num_channels > 0)
@@ -423,7 +424,7 @@
 
 	/* Client information */
 	out_uint16_le(s, SEC_TAG_CLI_INFO);
-	out_uint16_le(s, 216);	/* length */
+	out_uint16_le(s, 216 + (g_dpi > 0 ? 18 : 0));	/* length */
 	out_uint16_le(s, (g_rdp_version >= RDP_V5) ? 4 : 1);	/* RDP version. 1 == RDP4, 4 >= RDP5 to RDP8 */
 	out_uint16_le(s, 8);
 	out_uint16_le(s, g_width);
@@ -444,15 +445,25 @@
 	out_uint32_le(s, g_keyboard_functionkeys);
 	out_uint8s(s, 64);	/* reserved? 4 + 12 doublewords */
 	out_uint16_le(s, 0xca01);	/* colour depth? */
-	out_uint16_le(s, 1);
+	out_uint16_le(s, 1);		/* product id */
 
-	out_uint32(s, 0);
-	out_uint8(s, g_server_depth);
-	out_uint16_le(s, 0x0700);
+	out_uint32(s, 0);		/* serial number */
+	out_uint8(s, g_server_depth);	/* this stuff is misaligned should be 2,2,2,64,1,1 */
+	out_uint16_le(s, 0x0700);	/* this strange constant is split across fields */
 	out_uint8(s, 0);
 	out_uint32_le(s, 1);
 	out_uint8s(s, 64);
 	out_uint32_le(s, selected_protocol);	/* End of client info */
+	if (g_dpi > 0)
+	{
+		/* Extended client info describing monitor geometry */
+		out_uint32_le(s, g_width * 100 / (g_dpi * 254)); /* desktop physical width */
+		out_uint32_le(s, g_height * 100 / (g_dpi * 254)); /* desktop physical height */
+		out_uint16_le(s, 0); /* orientation: portrait */
+		out_uint32_le(s, g_dpi < 96 ? 100 : (g_dpi * 100 + 48) / 96); /* desktop scale factor */
+		out_uint32_le(s, g_dpi < 134 ? 100 : (g_dpi < 173 ? 140 : 180)); /* device scale factor */
+		/* the only allowed values for device scale factor are 100, 140, and 180. */
+	}
 
 	/* Write a Client Cluster Data (TS_UD_CS_CLUSTER) */
 	uint32 cluster_flags = 0;
@@ -901,7 +912,7 @@
 		return False;
 
 	/* We exchange some RDP data during the MCS-Connect */
-	mcs_data.size = 512;
+	mcs_data.size = 542;
 	mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
 	sec_out_mcs_data(&mcs_data, selected_proto);
 
diff -ru stock/rdesktop-1.8.3/xwin.c work/rdesktop-1.8.3/xwin.c
--- stock/rdesktop-1.8.3/xwin.c	2016-10-01 12:21:55.000000000 -0700
+++ work/rdesktop-1.8.3/xwin.c	2016-10-01 13:41:08.555214273 -0700
@@ -3097,9 +3097,13 @@
 void
 ui_set_cursor(RD_HCURSOR cursor)
 {
-	g_current_cursor = (Cursor) cursor;
-	XDefineCursor(g_display, g_wnd, g_current_cursor);
-	ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
+	extern RD_BOOL g_local_cursor;
+	if (!g_local_cursor)
+	{
+		g_current_cursor = (Cursor) cursor;
+		XDefineCursor(g_display, g_wnd, g_current_cursor);
+		ON_ALL_SEAMLESS_WINDOWS(XDefineCursor, (g_display, sw->wnd, g_current_cursor));
+	}
 }
 
 void

Reply via email to