ref: b71205289556e1c0baa4e68d46846c52ab675a1a
parent: 0beacde9afd629a61994d1eac8a084ddc4f357f7
author: Yaroslav Kolomiiets <yarikos@gmail.com>
date: Fri Mar 25 09:18:54 EDT 2016
fix freeze on connection to an existing session on 2008 server
--- a/dat.h
+++ b/dat.h
@@ -225,10 +225,10 @@
void activating(Rdp*,Share*);
void deactivating(Rdp*,Share*);
+void finalhandshake(Rdp*);
void scanimgupdate(Rdp*,Share*);
void scancmap(Rdp*,Share*);
void scanorders(Rdp*,Share*);
-
struct Imgupd {
int x;
--- a/mcs.c
+++ b/mcs.c
@@ -325,7 +325,7 @@
PLONG(p+16, 0x409); // keyboardLayout=us
PLONG(p+20, 2600); // clientBuild
memset(p+24, 32, 0); // clientName[32]
- toutf16(p+24, 32, sysname, strlen(sysname));
+ toutf16(p+24, 32, sysname, strlen(sysname)+1);
PSHORT(p+54, 0); // zero-terminateclientName
PLONG(p+56, 4); // keyboardType: 4="IBM enhanced (101-key or 102-key)"
PLONG(p+60, 0); // keyboardSubType
--- a/rd.c
+++ b/rd.c
@@ -224,7 +224,7 @@
readnet(Rdp* c)
{
Msg r;
-
+
for(;;){
if(readmsg(c, &r) <= 0)
return;
@@ -238,6 +238,11 @@
case Aupdate:
scanupdates(c, &r);
break;
+ case 0:
+ fprint(2, "unsupported PDU\n");
+ break;
+ default:
+ fprint(2, "r.type %d is not expected\n", r.type);
}
}
}
@@ -258,9 +263,16 @@
sysfatal("scanupdates: %r");
switch(u.type){
+ default:
+ if(u.type != 0)
+ fprint(2, "scanupdates: unhandled %d\n", u.type);
+ break;
case ShDeactivate:
deactivating(c, &u);
break;
+ case ShActivate: // server may engage capability re-exchange
+ activating(c, &u);
+ break;
case ShEinfo:
c->hupreason = u.err;
break;
@@ -276,45 +288,10 @@
case ShUwarp:
warpmouse(u.x, u.y);
break;
+ case Aflow:
+ break;
}
}
-}
-
-/* 2.2.1.13.1 Server Demand Active PDU */
-void
-activating(Rdp* c, Share* as)
-{
- Caps rcaps;
-
- if(getcaps(&rcaps, as->data, as->ndata) < 0)
- sysfatal("getcaps: %r");
- if(!rcaps.canrefresh)
- sysfatal("server can not Refresh Rect PDU");
- if(!rcaps.cansupress)
- sysfatal("server can not Suppress Output PDU");
- if(!rcaps.bitmap)
- sysfatal("server concealed their Bitmap Capabilities");
-
- switch(rcaps.depth){
- default: sysfatal("Unsupported server color depth: %uhd\n", rcaps.depth);
- case 8: c->chan = CMAP8; break;
- case 15: c->chan = RGB15; break;
- case 16: c->chan = RGB16; break;
- case 24: c->chan = RGB24; break;
- case 32: c->chan = XRGB32; break;
- }
- c->depth = rcaps.depth;
- c->xsz = rcaps.xsz;
- c->ysz = rcaps.ysz;
- c->srvchan = as->source;
- c->shareid = as->shareid;
- c->active = 1;
-}
-
-void
-deactivating(Rdp* c, Share*)
-{
- c->active = 0;
}
/* 2.2.9.1.1.3.1.2.1 Bitmap Update Data (TS_UPDATE_BITMAP_DATA) */
--- a/rpc.c
+++ b/rpc.c
@@ -158,7 +158,6 @@
case Mclosing:
werrstr("Disconnect Provider Ultimatum");
return -1;
- case Aflow:
case Ldone:
break;
case Lneedlicense:
@@ -169,27 +168,97 @@
if(r.getshare(&u, r.data, r.ndata) < 0)
return -1;
switch(u.type){
- case ShEinfo:
+ default:
+ fprint(2, "handshake: unhandled %d\n", u.type);
+ break;
+ case ShEinfo: /* do we really expect this here? */
c->hupreason = u.err;
break;
case ShActivate:
activating(c, &u);
- confirmactive(c);
- passinput(c, 0, InputSync, 0, 0, 0);
- assync(c);
- asctl(c, CAcooperate);
- asctl(c, CAreqctl);
- asfontls(c);
+ return 0;
+ }
+ }
+ }
+}
+
+/* 2.2.1.13.1 Server Demand Active PDU */
+void
+activating(Rdp* c, Share* as)
+{
+ Caps rcaps;
+
+ if(getcaps(&rcaps, as->data, as->ndata) < 0)
+ sysfatal("getcaps: %r");
+ if(!rcaps.canrefresh)
+ sysfatal("server can not Refresh Rect PDU");
+ if(!rcaps.cansupress)
+ sysfatal("server can not Suppress Output PDU");
+ if(!rcaps.bitmap)
+ sysfatal("server concealed their Bitmap Capabilities");
+
+ switch(rcaps.depth){
+ default: sysfatal("Unsupported server color depth: %uhd\n", rcaps.depth);
+ case 8: c->chan = CMAP8; break;
+ case 15: c->chan = RGB15; break;
+ case 16: c->chan = RGB16; break;
+ case 24: c->chan = RGB24; break;
+ case 32: c->chan = XRGB32; break;
+ }
+ c->depth = rcaps.depth;
+ c->xsz = rcaps.xsz;
+ c->ysz = rcaps.ysz;
+ c->srvchan = as->source;
+ c->shareid = as->shareid;
+ c->active = 1;
+
+ confirmactive(c);
+ finalhandshake(c);
+
+ passinput(c, 0, InputSync, 0, 0, 0);
+}
+
+void
+deactivating(Rdp* c, Share*)
+{
+ c->active = 0;
+}
+
+void
+finalhandshake(Rdp* c)
+{
+ Msg r;
+ Share u;
+
+ assync(c);
+ asctl(c, CAcooperate);
+ asctl(c, CAreqctl);
+ asfontls(c);
+
+ for(;;){
+ if(readmsg(c, &r) <= 0)
+ sysfatal("activating: readmsg: %r");
+ switch(r.type){
+ default:
+ fprint(2, "activating: unhandled PDU type %d\n", u.type);
+ break;
+ case Mclosing:
+ fprint(2, "disconnecting early");
+ return;
+ case Aupdate:
+ if(r.getshare(&u, r.data, r.ndata) < 0)
+ sysfatal("activating: r.getshare: %r");
+ switch(u.type){
+ default:
+ fprint(2, "activating: unhandled ASPDU type %d\n", u.type);
break;
- case ShDeactivate:
- deactivating(c, &u);
- break;
case ShSync:
case ShCtl:
+ /* responses to the assync(). asctl() calls above */
break;
case ShFmap:
- return 0;
- break;
+ /* finalized - we're good */
+ return;
}
}
}