25 |
{ |
{ |
26 |
HCONN conn; |
HCONN conn; |
27 |
RDP_ACTIVE_PDU active; |
RDP_ACTIVE_PDU active; |
|
RDP_DATA_HEADER hdr; |
|
|
RDP_UPDATE_PDU update; |
|
|
RDP_ORDER_STATE os; |
|
28 |
uint8 type; |
uint8 type; |
29 |
|
|
|
memset(&os, 0, sizeof(os)); |
|
|
|
|
30 |
if ((conn = mcs_connect(server)) == NULL) |
if ((conn = mcs_connect(server)) == NULL) |
31 |
return NULL; |
return NULL; |
32 |
|
|
34 |
mcs_recv(conn, False); /* Server's licensing certificate */ |
mcs_recv(conn, False); /* Server's licensing certificate */ |
35 |
rdp_send_cert(conn); |
rdp_send_cert(conn); |
36 |
mcs_recv(conn, False); |
mcs_recv(conn, False); |
37 |
|
mcs_recv(conn, False); /* Demand active */ |
38 |
|
|
39 |
if (rdp_recv_pdu(conn, &type) && (type != RDP_PDU_DEMAND_ACTIVE)) |
if (!rdp_recv_pdu(conn, &type) || (type != RDP_PDU_DEMAND_ACTIVE)) |
40 |
{ |
{ |
41 |
fprintf(stderr, "RDP error, expected Demand Active\n"); |
fprintf(stderr, "RDP error, expected Demand Active\n"); |
42 |
mcs_disconnect(conn); |
mcs_disconnect(conn); |
55 |
rdp_send_fonts(conn, 1); |
rdp_send_fonts(conn, 1); |
56 |
rdp_send_fonts(conn, 2); |
rdp_send_fonts(conn, 2); |
57 |
rdp_recv_pdu(conn, &type); // RDP_PDU_UNKNOWN 0x28 |
rdp_recv_pdu(conn, &type); // RDP_PDU_UNKNOWN 0x28 |
58 |
|
|
59 |
|
return conn; |
60 |
|
} |
61 |
|
|
62 |
|
void rdp_main_loop(HCONN conn) |
63 |
|
{ |
64 |
|
RDP_DATA_HEADER hdr; |
65 |
|
RDP_ORDER_STATE os; |
66 |
|
uint8 type; |
67 |
|
|
68 |
|
memset(&os, 0, sizeof(os)); |
69 |
|
|
70 |
while (rdp_recv_pdu(conn, &type)) |
while (rdp_recv_pdu(conn, &type)) |
71 |
{ |
{ |
72 |
if (type != RDP_PDU_DATA) |
if (type != RDP_PDU_DATA) |
73 |
|
{ |
74 |
|
fprintf(stderr, "Unknown PDU 0x%x\n", type); |
75 |
continue; |
continue; |
76 |
|
} |
77 |
|
|
78 |
rdp_io_data_header(&conn->in, &hdr); |
rdp_io_data_header(&conn->in, &hdr); |
79 |
|
|
80 |
switch (hdr.data_pdu_type) |
switch (hdr.data_pdu_type) |
81 |
{ |
{ |
82 |
case RDP_DATA_PDU_UPDATE: |
case RDP_DATA_PDU_UPDATE: |
83 |
rdp_io_update_pdu(&conn->in, &update); |
process_update(conn, &os); |
84 |
if (update.update_type == RDP_UPDATE_ORDERS) |
break; |
85 |
{ |
|
86 |
fprintf(stderr, "Received orders\n"); |
case RDP_DATA_PDU_POINTER: |
87 |
process_orders(conn, &os); |
process_pointer(conn); |
88 |
} |
break; |
89 |
break; |
|
90 |
|
default: |
91 |
|
fprintf(stderr, "Unknown data PDU 0x%x\n", |
92 |
|
hdr.data_pdu_type); |
93 |
} |
} |
94 |
} |
} |
|
|
|
|
return conn; |
|
95 |
} |
} |
96 |
|
|
97 |
void prs_io_coord(STREAM s, uint16 *coord, BOOL delta) |
void process_memblt(HCONN conn, RDP_ORDER_STATE *os, BOOL delta) |
98 |
{ |
{ |
99 |
uint8 change; |
HBITMAP hbitmap; |
100 |
|
uint16 present; |
101 |
|
lsb_io_uint16(&conn->in, &present); |
102 |
|
|
103 |
if (delta) |
if (present & 1) |
104 |
|
prs_io_uint8(&conn->in, &os->memblt.cache_id); |
105 |
|
|
106 |
|
if (present & 2) |
107 |
|
rdp_io_coord(&conn->in, &os->memblt.x, delta); |
108 |
|
|
109 |
|
if (present & 4) |
110 |
|
rdp_io_coord(&conn->in, &os->memblt.y, delta); |
111 |
|
|
112 |
|
if (present & 8) |
113 |
|
rdp_io_coord(&conn->in, &os->memblt.cx, delta); |
114 |
|
|
115 |
|
if (present & 16) |
116 |
|
rdp_io_coord(&conn->in, &os->memblt.cy, delta); |
117 |
|
|
118 |
|
if (present & 32) |
119 |
|
prs_io_uint8(&conn->in, &os->memblt.opcode); |
120 |
|
|
121 |
|
if (present & 256) |
122 |
|
lsb_io_uint16(&conn->in, &os->memblt.cache_idx); |
123 |
|
|
124 |
|
if (os->memblt.opcode != 0xcc) /* SRCCOPY */ |
125 |
{ |
{ |
126 |
prs_io_uint8(s, &change); |
fprintf(stderr, "Unsupported raster operation 0x%x\n", |
127 |
*coord += change; |
os->memblt.opcode); |
128 |
|
return; |
129 |
} |
} |
130 |
else |
|
131 |
|
if ((os->memblt.cache_idx > NUM_ELEMENTS(conn->bmpcache)) |
132 |
|
|| ((hbitmap = conn->bmpcache[os->memblt.cache_idx]) == NULL)) |
133 |
{ |
{ |
134 |
lsb_io_uint16(s, coord); |
fprintf(stderr, "Bitmap %d not found\n", os->memblt.cache_idx); |
135 |
|
return; |
136 |
} |
} |
137 |
|
|
138 |
|
fprintf(stderr, "MEMBLT %d:%dx%d\n", os->memblt.cache_idx, |
139 |
|
os->memblt.x, os->memblt.y); |
140 |
|
|
141 |
|
ui_paint_bitmap(conn->wnd, hbitmap, os->memblt.x, os->memblt.y); |
142 |
} |
} |
143 |
|
|
144 |
void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta) |
void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta) |
147 |
prs_io_uint8(&conn->in, &present); |
prs_io_uint8(&conn->in, &present); |
148 |
|
|
149 |
if (present & 1) |
if (present & 1) |
150 |
prs_io_coord(&conn->in, &os->opaque_rect.x, delta); |
rdp_io_coord(&conn->in, &os->opaque_rect.x, delta); |
151 |
|
|
152 |
if (present & 2) |
if (present & 2) |
153 |
prs_io_coord(&conn->in, &os->opaque_rect.y, delta); |
rdp_io_coord(&conn->in, &os->opaque_rect.y, delta); |
154 |
|
|
155 |
if (present & 4) |
if (present & 4) |
156 |
prs_io_coord(&conn->in, &os->opaque_rect.cx, delta); |
rdp_io_coord(&conn->in, &os->opaque_rect.cx, delta); |
157 |
|
|
158 |
if (present & 8) |
if (present & 8) |
159 |
prs_io_coord(&conn->in, &os->opaque_rect.cy, delta); |
rdp_io_coord(&conn->in, &os->opaque_rect.cy, delta); |
160 |
|
|
161 |
if (present & 16) |
if (present & 16) |
162 |
prs_io_uint8(&conn->in, &os->opaque_rect.colour); |
prs_io_uint8(&conn->in, &os->opaque_rect.colour); |
163 |
|
|
164 |
fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y); |
fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y); |
165 |
|
ui_draw_rectangle(conn->wnd, os->opaque_rect.x, os->opaque_rect.y, |
166 |
|
os->opaque_rect.cx, os->opaque_rect.cy); |
167 |
|
} |
168 |
|
|
169 |
|
void process_bmpcache(HCONN conn) |
170 |
|
{ |
171 |
|
RDP_BITMAP_HEADER rbh; |
172 |
|
HBITMAP *entry; |
173 |
|
char *input, *bmpdata; |
174 |
|
|
175 |
|
rdp_io_bitmap_header(&conn->in, &rbh); |
176 |
|
fprintf(stderr, "BMPCACHE %d:%dx%d\n", rbh.cache_idx, |
177 |
|
rbh.width, rbh.height); |
178 |
|
|
179 |
|
input = conn->in.data + conn->in.offset; |
180 |
|
conn->in.offset += rbh.size; |
181 |
|
// dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset); |
182 |
|
|
183 |
|
bmpdata = malloc(rbh.width * rbh.height); |
184 |
|
if (!bitmap_decompress(bmpdata, rbh.width, rbh.height, input, rbh.size)) |
185 |
|
{ |
186 |
|
fprintf(stderr, "Decompression failed\n"); |
187 |
|
free(bmpdata); |
188 |
|
return; |
189 |
|
} |
190 |
|
|
191 |
|
if (rbh.cache_idx > NUM_ELEMENTS(conn->bmpcache)) |
192 |
|
{ |
193 |
|
fprintf(stderr, "Attempted store past end of cache"); |
194 |
|
return; |
195 |
|
} |
196 |
|
|
197 |
|
entry = &conn->bmpcache[rbh.cache_idx]; |
198 |
|
// if (*entry != NULL) |
199 |
|
// ui_destroy_bitmap(conn->wnd, *entry); |
200 |
|
|
201 |
|
*entry = ui_create_bitmap(conn->wnd, rbh.width, rbh.height, bmpdata); |
202 |
|
// ui_paint_bitmap(conn->wnd, bmp, x, 0); |
203 |
|
// ui_destroy_bitmap(conn->wnd, bmp); |
204 |
} |
} |
205 |
|
|
206 |
void process_orders(HCONN conn, RDP_ORDER_STATE *os) |
void process_orders(HCONN conn, RDP_ORDER_STATE *os) |
208 |
uint16 num_orders; |
uint16 num_orders; |
209 |
int processed = 0; |
int processed = 0; |
210 |
BOOL res = True; |
BOOL res = True; |
211 |
|
BOOL delta; |
212 |
// unsigned char *p; |
// unsigned char *p; |
213 |
|
|
214 |
lsb_io_uint16(&conn->in, &num_orders); |
lsb_io_uint16(&conn->in, &num_orders); |
223 |
uint8 order_flags; |
uint8 order_flags; |
224 |
|
|
225 |
prs_io_uint8(&conn->in, &order_flags); |
prs_io_uint8(&conn->in, &order_flags); |
226 |
|
fprintf(stderr, "Order flags: 0x%x\n", order_flags); |
227 |
|
|
228 |
|
if (order_flags == 0x51) /* ?? */ |
229 |
|
return; |
230 |
|
|
231 |
if (!(order_flags & RDP_ORDER_STANDARD)) |
if (!(order_flags & RDP_ORDER_STANDARD)) |
232 |
return; |
return; |
239 |
switch (rso.type) |
switch (rso.type) |
240 |
{ |
{ |
241 |
case RDP_ORDER_BMPCACHE: |
case RDP_ORDER_BMPCACHE: |
242 |
{ |
process_bmpcache(conn); |
|
RDP_BITMAP_HEADER rbh; |
|
|
char output[8192]; |
|
|
|
|
|
rdp_io_bitmap_header(&conn->in, &rbh); |
|
|
fprintf(stderr, "Decompressing bitmap %d x %d, final size %d\n", rbh.width, rbh.height, rbh.final_size); |
|
|
bitmap_decompress(conn->in.data |
|
|
+ conn->in.offset, rbh.size, |
|
|
output, rbh.width); |
|
|
conn->in.offset += rbh.size; |
|
243 |
break; |
break; |
|
} |
|
244 |
default: |
default: |
245 |
fprintf(stderr, "Unknown secondary order %d\n", |
fprintf(stderr, "Unknown secondary order %d\n", |
246 |
rso.type); |
rso.type); |
247 |
return; |
return; |
248 |
} |
} |
249 |
|
} |
250 |
|
else |
251 |
|
{ |
252 |
|
if (order_flags & RDP_ORDER_CHANGE) |
253 |
|
prs_io_uint8(&conn->in, &os->order_type); |
254 |
|
|
255 |
|
delta = order_flags & RDP_ORDER_DELTA; |
256 |
|
|
257 |
|
switch (os->order_type) |
258 |
|
{ |
259 |
|
case RDP_ORDER_OPAQUE_RECT: |
260 |
|
process_opaque_rect(conn, os, delta); |
261 |
|
break; |
262 |
|
|
263 |
|
case RDP_ORDER_MEMBLT: |
264 |
|
process_memblt(conn, os, delta); |
265 |
|
break; |
266 |
|
|
267 |
|
default: |
268 |
|
fprintf(stderr, "Unknown order %d\n", os->order_type); |
269 |
|
return; |
270 |
|
} |
271 |
} |
} |
272 |
|
|
273 |
if (order_flags & RDP_ORDER_CHANGE) |
processed++; |
274 |
prs_io_uint8(&conn->in, &os->order_type); |
} |
275 |
|
} |
276 |
|
|
277 |
switch (os->order_type) |
void process_palette(HCONN conn) |
278 |
{ |
{ |
279 |
case RDP_ORDER_OPAQUE_RECT: |
HCOLORMAP map; |
280 |
process_opaque_rect(conn, os, order_flags & RDP_ORDER_DELTA); |
COLORMAP colors; |
281 |
|
|
282 |
|
rdp_io_colormap(&conn->in, &colors); |
283 |
|
map = ui_create_colormap(conn->wnd, &colors); |
284 |
|
ui_set_colormap(conn->wnd, map); |
285 |
|
// ui_destroy_colormap(map); |
286 |
|
} |
287 |
|
|
288 |
|
void process_update(HCONN conn, RDP_ORDER_STATE *os) |
289 |
|
{ |
290 |
|
RDP_UPDATE_PDU update; |
291 |
|
|
292 |
|
rdp_io_update_pdu(&conn->in, &update); |
293 |
|
switch (update.update_type) |
294 |
|
{ |
295 |
|
case RDP_UPDATE_ORDERS: |
296 |
|
process_orders(conn, os); |
297 |
|
break; |
298 |
|
case RDP_UPDATE_PALETTE: |
299 |
|
process_palette(conn); |
300 |
|
break; |
301 |
|
case RDP_UPDATE_SYNCHRONIZE: |
302 |
break; |
break; |
303 |
default: |
default: |
304 |
fprintf(stderr, "Unknown order %d\n", os->order_type); |
fprintf(stderr, "Unknown update 0x%x\n", |
305 |
return; |
update.update_type); |
306 |
} |
} |
307 |
|
|
308 |
processed++; |
} |
309 |
|
|
310 |
|
void process_pointer(HCONN conn) |
311 |
|
{ |
312 |
|
RDP_POINTER ptr; |
313 |
|
|
314 |
|
rdp_io_pointer(&conn->in, &ptr); |
315 |
|
|
316 |
|
switch (ptr.message) |
317 |
|
{ |
318 |
|
case RDP_POINTER_MOVE: |
319 |
|
ui_move_pointer(conn->wnd, ptr.x, ptr.y); |
320 |
|
break; |
321 |
|
default: |
322 |
|
fprintf(stderr, "Unknown pointer message 0x%x\n", |
323 |
|
ptr.message); |
324 |
} |
} |
325 |
} |
} |
326 |
|
|
535 |
{ |
{ |
536 |
RDP_HEADER hdr; |
RDP_HEADER hdr; |
537 |
|
|
538 |
if (!mcs_recv(conn, False) || !rdp_io_header(&conn->in, &hdr)) |
conn->in.offset = conn->in.rdp_offset; |
539 |
|
|
540 |
|
if (conn->in.offset >= conn->in.end) |
541 |
|
{ |
542 |
|
if (!mcs_recv(conn, False)) |
543 |
|
return False; |
544 |
|
} |
545 |
|
|
546 |
|
if (!rdp_io_header(&conn->in, &hdr)) |
547 |
return False; |
return False; |
548 |
|
|
549 |
|
conn->in.rdp_offset += hdr.length; |
550 |
*type = hdr.pdu_type & 0xf; |
*type = hdr.pdu_type & 0xf; |
551 |
|
|
552 |
|
#if DEBUG |
553 |
|
fprintf(stderr, "RDP packet (type %x):\n", *type); |
554 |
|
dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset); |
555 |
|
#endif |
556 |
|
|
557 |
return True; |
return True; |
558 |
} |
} |
559 |
|
|
755 |
return res; |
return res; |
756 |
} |
} |
757 |
|
|
758 |
|
BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta) |
759 |
|
{ |
760 |
|
uint8 change; |
761 |
|
BOOL res; |
762 |
|
|
763 |
|
if (delta) |
764 |
|
{ |
765 |
|
res = prs_io_uint8(s, &change); |
766 |
|
*coord += change; |
767 |
|
} |
768 |
|
else |
769 |
|
{ |
770 |
|
res = lsb_io_uint16(s, coord); |
771 |
|
} |
772 |
|
|
773 |
|
return res; |
774 |
|
} |
775 |
|
|
776 |
|
BOOL rdp_io_colormap(STREAM s, COLORMAP *colors) |
777 |
|
{ |
778 |
|
int datasize; |
779 |
|
|
780 |
|
lsb_io_uint16(s, &colors->ncolors); |
781 |
|
datasize = colors->ncolors * 3; |
782 |
|
|
783 |
|
if (datasize > sizeof(colors->colors)) |
784 |
|
return False; |
785 |
|
|
786 |
|
memcpy(colors->colors, s->data + s->offset, datasize); |
787 |
|
s->offset += datasize; |
788 |
|
return True; |
789 |
|
} |
790 |
|
|
791 |
BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps) |
BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps) |
792 |
{ |
{ |
793 |
uint16 length = RDP_CAPLEN_GENERAL; |
uint16 length = RDP_CAPLEN_GENERAL; |
1316 |
|
|
1317 |
return res; |
return res; |
1318 |
} |
} |
1319 |
|
|
1320 |
|
BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr) |
1321 |
|
{ |
1322 |
|
BOOL res = True; |
1323 |
|
|
1324 |
|
res = res ? lsb_io_uint16(s, &ptr->message) : False; |
1325 |
|
res = res ? lsb_io_uint16(s, &ptr->pad ) : False; |
1326 |
|
res = res ? lsb_io_uint16(s, &ptr->x ) : False; |
1327 |
|
res = res ? lsb_io_uint16(s, &ptr->y ) : False; |
1328 |
|
|
1329 |
|
return res; |
1330 |
|
} |