/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 7 by matty, Fri Jul 7 09:40:03 2000 UTC revision 865 by stargo, Tue Mar 15 11:25:50 2005 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP layer     Protocol services - RDP layer
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include <time.h>
22    #include <errno.h>
23    #include <unistd.h>
24    #include "rdesktop.h"
25    
26    #ifdef HAVE_ICONV
27    #ifdef HAVE_ICONV_H
28    #include <iconv.h>
29    #endif
30    
31  /* Establish a connection up to the RDP layer */  #ifndef ICONV_CONST
32  HCONN rdp_connect(char *server)  #define ICONV_CONST ""
33  {  #endif
34          HCONN conn;  #endif
         RDP_ACTIVE_PDU active;  
         uint8 type;  
35    
36          if ((conn = mcs_connect(server)) == NULL)  extern uint16 g_mcs_userid;
37                  return NULL;  extern char g_username[64];
38    extern char g_codepage[16];
39    extern BOOL g_bitmap_compression;
40    extern BOOL g_orders;
41    extern BOOL g_encryption;
42    extern BOOL g_desktop_save;
43    extern BOOL g_polygon_ellipse_orders;
44    extern BOOL g_use_rdp5;
45    extern uint16 g_server_rdp_version;
46    extern uint32 g_rdp5_performanceflags;
47    extern int g_server_bpp;
48    extern int g_width;
49    extern int g_height;
50    extern BOOL g_bitmap_cache;
51    extern BOOL g_bitmap_cache_persist_enable;
52    
53          rdp_establish_key(conn);  uint8 *g_next_packet;
54          mcs_recv(conn, False); /* Server's licensing certificate */  uint32 g_rdp_shareid;
         rdp_send_cert(conn);  
         mcs_recv(conn, False);  
         mcs_recv(conn, False); /* Demand active */  
   
         if (!rdp_recv_pdu(conn, &type) || (type != RDP_PDU_DEMAND_ACTIVE))  
         {  
                 fprintf(stderr, "RDP error, expected Demand Active\n");  
                 mcs_disconnect(conn);  
                 return NULL;  
         }  
   
         rdp_io_active_pdu(&conn->in, &active, RDP_PDU_DEMAND_ACTIVE);  
         rdp_send_confirm_active(conn);  
         rdp_send_synchronize(conn);  
         rdp_send_control(conn, RDP_CTL_COOPERATE);  
         rdp_send_control(conn, RDP_CTL_REQUEST_CONTROL);  
         rdp_recv_pdu(conn, &type); // RDP_PDU_SYNCHRONIZE  
         rdp_recv_pdu(conn, &type); // RDP_CTL_COOPERATE  
         rdp_recv_pdu(conn, &type); // RDP_CTL_GRANT_CONTROL  
         rdp_send_input(conn);  
         rdp_send_fonts(conn, 1);  
         rdp_send_fonts(conn, 2);  
         rdp_recv_pdu(conn, &type); // RDP_PDU_UNKNOWN 0x28  
55    
56          return conn;  extern RDPCOMP g_mppc_dict;
 }  
57    
58  void rdp_main_loop(HCONN conn)  #if WITH_DEBUG
59  {  static uint32 g_packetno;
60          RDP_DATA_HEADER hdr;  #endif
         RDP_ORDER_STATE os;  
         uint8 type;  
61    
62          memset(&os, 0, sizeof(os));  #ifdef HAVE_ICONV
63    static BOOL g_iconv_works = True;
64    #endif
65    
66          while (rdp_recv_pdu(conn, &type))  /* Receive an RDP packet */
67          {  static STREAM
68                  if (type != RDP_PDU_DATA)  rdp_recv(uint8 * type)
69    {
70            static STREAM rdp_s;
71            uint16 length, pdu_type;
72            uint8 rdpver;
73    
74            if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
75            {
76                    rdp_s = sec_recv(&rdpver);
77                    if (rdp_s == NULL)
78                            return NULL;
79                    if (rdpver == 0xff)
80                  {                  {
81                          fprintf(stderr, "Unknown PDU 0x%x\n", type);                          g_next_packet = rdp_s->end;
82                          continue;                          *type = 0;
83                            return rdp_s;
84                  }                  }
85                    else if (rdpver != 3)
                 rdp_io_data_header(&conn->in, &hdr);  
   
                 switch (hdr.data_pdu_type)  
86                  {                  {
87                          case RDP_DATA_PDU_UPDATE:                          /* rdp5_process should move g_next_packet ok */
88                                  process_update(conn, &os);                          rdp5_process(rdp_s);
89                                  break;                          *type = 0;
90                            return rdp_s;
91                    }
92    
93                          case RDP_DATA_PDU_POINTER:                  g_next_packet = rdp_s->p;
94                                  process_pointer(conn);          }
95                                  break;          else
96            {
97                    rdp_s->p = g_next_packet;
98            }
99    
100                          default:          in_uint16_le(rdp_s, length);
101                                  fprintf(stderr, "Unknown data PDU 0x%x\n",          /* 32k packets are really 8, keepalive fix */
102                                                  hdr.data_pdu_type);          if (length == 0x8000)
103                  }          {
104                    g_next_packet += 8;
105                    *type = 0;
106                    return rdp_s;
107          }          }
108            in_uint16_le(rdp_s, pdu_type);
109            in_uint8s(rdp_s, 2);    /* userid */
110            *type = pdu_type & 0xf;
111    
112    #if WITH_DEBUG
113            DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
114            hexdump(g_next_packet, length);
115    #endif /*  */
116    
117            g_next_packet += length;
118            return rdp_s;
119  }  }
120    
121  void process_memblt(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)  /* Initialise an RDP data packet */
122    static STREAM
123    rdp_init_data(int maxlen)
124  {  {
125          HBITMAP hbitmap;          STREAM s;
         uint16 present;  
         lsb_io_uint16(&conn->in, &present);  
126    
127          if (present & 1)          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
128                  prs_io_uint8(&conn->in, &os->memblt.cache_id);          s_push_layer(s, rdp_hdr, 18);
129    
130          if (present & 2)          return s;
131                  rdp_io_coord(&conn->in, &os->memblt.x, delta);  }
132    
133          if (present & 4)  /* Send an RDP data packet */
134                  rdp_io_coord(&conn->in, &os->memblt.y, delta);  static void
135    rdp_send_data(STREAM s, uint8 data_pdu_type)
136    {
137            uint16 length;
138    
139          if (present & 8)          s_pop_layer(s, rdp_hdr);
140                  rdp_io_coord(&conn->in, &os->memblt.cx, delta);          length = s->end - s->p;
141    
142          if (present & 16)          out_uint16_le(s, length);
143                  rdp_io_coord(&conn->in, &os->memblt.cy, delta);          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
144            out_uint16_le(s, (g_mcs_userid + 1001));
145    
146          if (present & 32)          out_uint32_le(s, g_rdp_shareid);
147                  prs_io_uint8(&conn->in, &os->memblt.opcode);          out_uint8(s, 0);        /* pad */
148            out_uint8(s, 1);        /* streamid */
149            out_uint16_le(s, (length - 14));
150            out_uint8(s, data_pdu_type);
151            out_uint8(s, 0);        /* compress_type */
152            out_uint16(s, 0);       /* compress_len */
153    
154          if (present & 256)          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
155                  lsb_io_uint16(&conn->in, &os->memblt.cache_idx);  }
156    
157          if (os->memblt.opcode != 0xcc) /* SRCCOPY */  /* Output a string in Unicode */
158          {  void
159                  fprintf(stderr, "Unsupported raster operation 0x%x\n",  rdp_out_unistr(STREAM s, char *string, int len)
160                          os->memblt.opcode);  {
161                  return;  #ifdef HAVE_ICONV
162          }          size_t ibl = strlen(string), obl = len + 2;
163            static iconv_t iconv_h = (iconv_t) - 1;
164            char *pin = string, *pout = s->p;
165    
166            memset(pout, 0, len + 4);
167    
168          if ((os->memblt.cache_idx > NUM_ELEMENTS(conn->bmpcache))          if (g_iconv_works)
             || ((hbitmap = conn->bmpcache[os->memblt.cache_idx]) == NULL))  
169          {          {
170                  fprintf(stderr, "Bitmap %d not found\n", os->memblt.cache_idx);                  if (iconv_h == (iconv_t) - 1)
171                  return;                  {
172          }                          size_t i = 1, o = 4;
173                            if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
174                            {
175                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
176                                            g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
177    
178          fprintf(stderr, "MEMBLT %d:%dx%d\n", os->memblt.cache_idx,                                  g_iconv_works = False;
179                                          os->memblt.x, os->memblt.y);                                  return (rdp_out_unistr(s, string, len));
180                            }
181                            if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
182                                (size_t) - 1)
183                            {
184                                    iconv_close(iconv_h);
185                                    iconv_h = (iconv_t) - 1;
186                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
187    
188          ui_paint_bitmap(conn->wnd, hbitmap, os->memblt.x, os->memblt.y);                                  g_iconv_works = False;
189  }                                  return (rdp_out_unistr(s, string, len));
190                            }
191                            pin = string;
192                            pout = (char *) s->p;
193                    }
194    
195  void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
196  {                  {
197          uint8 present;                          iconv_close(iconv_h);
198          prs_io_uint8(&conn->in, &present);                          iconv_h = (iconv_t) - 1;
199                            warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
200    
201          if (present & 1)                          g_iconv_works = False;
202                  rdp_io_coord(&conn->in, &os->opaque_rect.x, delta);                          return (rdp_out_unistr(s, string, len));
203                    }
204    
205          if (present & 2)                  s->p += len + 2;
                 rdp_io_coord(&conn->in, &os->opaque_rect.y, delta);  
206    
207          if (present & 4)          }
208                  rdp_io_coord(&conn->in, &os->opaque_rect.cx, delta);          else
209    #endif
210            {
211                    int i = 0, j = 0;
212    
213          if (present & 8)                  len += 2;
                 rdp_io_coord(&conn->in, &os->opaque_rect.cy, delta);  
214    
215          if (present & 16)                  while (i < len)
216                  prs_io_uint8(&conn->in, &os->opaque_rect.colour);                  {
217                            s->p[i++] = string[j++];
218                            s->p[i++] = 0;
219                    }
220    
221          fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y);                  s->p += len;
222          ui_draw_rectangle(conn->wnd, os->opaque_rect.x, os->opaque_rect.y,          }
                                 os->opaque_rect.cx, os->opaque_rect.cy);  
223  }  }
224    
225  void process_bmpcache(HCONN conn)  /* Input a string in Unicode
226     *
227     * Returns str_len of string
228     */
229    int
230    rdp_in_unistr(STREAM s, char *string, int uni_len)
231  {  {
232          RDP_BITMAP_HEADER rbh;  #ifdef HAVE_ICONV
233          HBITMAP *entry;          size_t ibl = uni_len, obl = uni_len;
234          char *input, *bmpdata;          char *pin = s->p, *pout = string;
235            static iconv_t iconv_h = (iconv_t) - 1;
236    
237          rdp_io_bitmap_header(&conn->in, &rbh);          if (g_iconv_works)
238          fprintf(stderr, "BMPCACHE %d:%dx%d\n", rbh.cache_idx,          {
239                                  rbh.width, rbh.height);                  if (iconv_h == (iconv_t) - 1)
240                    {
241                            if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
242                            {
243                                    warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
244                                            WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
245    
246          input = conn->in.data + conn->in.offset;                                  g_iconv_works = False;
247          conn->in.offset += rbh.size;                                  return rdp_in_unistr(s, string, uni_len);
248  //      dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset);                          }
249                    }
250    
251          bmpdata = malloc(rbh.width * rbh.height);                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
252          if (!bitmap_decompress(bmpdata, rbh.width, rbh.height, input, rbh.size))                  {
253          {                          iconv_close(iconv_h);
254                  fprintf(stderr, "Decompression failed\n");                          iconv_h = (iconv_t) - 1;
255                  free(bmpdata);                          warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
                 return;  
         }  
256    
257          if (rbh.cache_idx > NUM_ELEMENTS(conn->bmpcache))                          g_iconv_works = False;
258          {                          return rdp_in_unistr(s, string, uni_len);
259                  fprintf(stderr, "Attempted store past end of cache");                  }
260                  return;                  return pout - string;
261          }          }
262            else
263    #endif
264            {
265                    int i = 0;
266    
267          entry = &conn->bmpcache[rbh.cache_idx];                  while (i < uni_len / 2)
268          // if (*entry != NULL)                  {
269          //      ui_destroy_bitmap(conn->wnd, *entry);                          in_uint8a(s, &string[i++], 1);
270                            in_uint8s(s, 1);
271                    }
272    
273          *entry = ui_create_bitmap(conn->wnd, rbh.width, rbh.height, bmpdata);                  return i - 1;
274          //      ui_paint_bitmap(conn->wnd, bmp, x, 0);          }
         //      ui_destroy_bitmap(conn->wnd, bmp);  
275  }  }
276    
 void process_orders(HCONN conn, RDP_ORDER_STATE *os)  
 {  
         uint16 num_orders;  
         int processed = 0;  
         BOOL res = True;  
         BOOL delta;  
         //      unsigned char *p;  
   
         lsb_io_uint16(&conn->in, &num_orders);  
   
         conn->in.offset += 2;  
         //      p = &conn->in.data[conn->in.offset];  
277    
278          //      fprintf(stderr, "%02X %02X %02X %02X\n", p[0], p[1], p[2], p[3]);  /* Parse a logon info packet */
279    static void
280    rdp_send_logon_info(uint32 flags, char *domain, char *user,
281                        char *password, char *program, char *directory)
282    {
283            char *ipaddr = tcp_get_address();
284            int len_domain = 2 * strlen(domain);
285            int len_user = 2 * strlen(user);
286            int len_password = 2 * strlen(password);
287            int len_program = 2 * strlen(program);
288            int len_directory = 2 * strlen(directory);
289            int len_ip = 2 * strlen(ipaddr);
290            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
291            int packetlen = 0;
292            uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
293            STREAM s;
294            time_t t = time(NULL);
295            time_t tzone;
296    
297    #if 0
298            /* enable rdp compression */
299            /* some problems still exist with rdp5 */
300            flags |= RDP_COMPRESSION;
301    #endif
302    
303          while ((processed < num_orders) && res)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
304          {          {
305                  uint8 order_flags;                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
306    
307                  prs_io_uint8(&conn->in, &order_flags);                  s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
308                  fprintf(stderr, "Order flags: 0x%x\n", order_flags);                               + len_program + len_directory + 10);
309    
310                  if (order_flags == 0x51) /* ?? */                  out_uint32(s, 0);
311                          return;                  out_uint32_le(s, flags);
312                    out_uint16_le(s, len_domain);
313                    out_uint16_le(s, len_user);
314                    out_uint16_le(s, len_password);
315                    out_uint16_le(s, len_program);
316                    out_uint16_le(s, len_directory);
317                    rdp_out_unistr(s, domain, len_domain);
318                    rdp_out_unistr(s, user, len_user);
319                    rdp_out_unistr(s, password, len_password);
320                    rdp_out_unistr(s, program, len_program);
321                    rdp_out_unistr(s, directory, len_directory);
322            }
323            else
324            {
325    
326                  if (!(order_flags & RDP_ORDER_STANDARD))                  flags |= RDP_LOGON_BLOB;
327                          return;                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
328                    packetlen = 4 + /* Unknown uint32 */
329                            4 +     /* flags */
330                            2 +     /* len_domain */
331                            2 +     /* len_user */
332                            (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
333                            (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
334                            2 +     /* len_program */
335                            2 +     /* len_directory */
336                            (0 < len_domain ? len_domain : 2) +     /* domain */
337                            len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
338                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
339                            (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
340                            2 +     /* Client ip length */
341                            len_ip +        /* Client ip */
342                            2 +     /* DLL string length */
343                            len_dll +       /* DLL string */
344                            2 +     /* Unknown */
345                            2 +     /* Unknown */
346                            64 +    /* Time zone #0 */
347                            2 +     /* Unknown */
348                            64 +    /* Time zone #1 */
349                            32;     /* Unknown */
350    
351                    s = sec_init(sec_flags, packetlen);
352                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
353    
354                    out_uint32(s, 0);       /* Unknown */
355                    out_uint32_le(s, flags);
356                    out_uint16_le(s, len_domain);
357                    out_uint16_le(s, len_user);
358                    if (flags & RDP_LOGON_AUTO)
359                    {
360                            out_uint16_le(s, len_password);
361    
362                  if (order_flags & RDP_ORDER_SECONDARY)                  }
363                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
364                    {
365                            out_uint16_le(s, 0);
366                    }
367                    out_uint16_le(s, len_program);
368                    out_uint16_le(s, len_directory);
369                    if (0 < len_domain)
370                            rdp_out_unistr(s, domain, len_domain);
371                    else
372                            out_uint16_le(s, 0);
373                    rdp_out_unistr(s, user, len_user);
374                    if (flags & RDP_LOGON_AUTO)
375                  {                  {
376                          RDP_SECONDARY_ORDER rso;                          rdp_out_unistr(s, password, len_password);
377                    }
378                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
379                    {
380                            out_uint16_le(s, 0);
381                    }
382                    if (0 < len_program)
383                    {
384                            rdp_out_unistr(s, program, len_program);
385    
                         rdp_io_secondary_order(&conn->in, &rso);  
                         switch (rso.type)  
                         {  
                         case RDP_ORDER_BMPCACHE:  
                                 process_bmpcache(conn);  
                                 break;  
                         default:  
                                 fprintf(stderr, "Unknown secondary order %d\n",  
                                         rso.type);  
                                 return;  
                         }  
386                  }                  }
387                  else                  else
388                  {                  {
389                          if (order_flags & RDP_ORDER_CHANGE)                          out_uint16_le(s, 0);
390                                  prs_io_uint8(&conn->in, &os->order_type);                  }
391                    if (0 < len_directory)
392                    {
393                            rdp_out_unistr(s, directory, len_directory);
394                    }
395                    else
396                    {
397                            out_uint16_le(s, 0);
398                    }
399                    out_uint16_le(s, 2);
400                    out_uint16_le(s, len_ip + 2);   /* Length of client ip */
401                    rdp_out_unistr(s, ipaddr, len_ip);
402                    out_uint16_le(s, len_dll + 2);
403                    rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
404    
405                          delta = order_flags & RDP_ORDER_DELTA;                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
406                    out_uint32_le(s, tzone);
407    
408                          switch (os->order_type)                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
409                          {                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
                         case RDP_ORDER_OPAQUE_RECT:  
                                 process_opaque_rect(conn, os, delta);  
                                 break;  
410    
411                          case RDP_ORDER_MEMBLT:                  out_uint32_le(s, 0x0a0000);
412                                  process_memblt(conn, os, delta);                  out_uint32_le(s, 0x050000);
413                                  break;                  out_uint32_le(s, 3);
414                    out_uint32_le(s, 0);
415                    out_uint32_le(s, 0);
416    
417                    rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
418                    out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
419    
420                    out_uint32_le(s, 0x30000);
421                    out_uint32_le(s, 0x050000);
422                    out_uint32_le(s, 2);
423                    out_uint32(s, 0);
424                    out_uint32_le(s, 0xffffffc4);
425                    out_uint32_le(s, 0xfffffffe);
426                    out_uint32_le(s, g_rdp5_performanceflags);
427                    out_uint32(s, 0);
428    
                         default:  
                                 fprintf(stderr, "Unknown order %d\n", os->order_type);  
                                 return;  
                         }  
                 }  
429    
                 processed++;  
430          }          }
431            s_mark_end(s);
432            sec_send(s, sec_flags);
433  }  }
434    
435  void process_palette(HCONN conn)  /* Send a control PDU */
436    static void
437    rdp_send_control(uint16 action)
438  {  {
439          HCOLORMAP map;          STREAM s;
440          COLORMAP colors;  
441            s = rdp_init_data(8);
442    
443            out_uint16_le(s, action);
444            out_uint16(s, 0);       /* userid */
445            out_uint32(s, 0);       /* control id */
446    
447          rdp_io_colormap(&conn->in, &colors);          s_mark_end(s);
448          map = ui_create_colormap(conn->wnd, &colors);          rdp_send_data(s, RDP_DATA_PDU_CONTROL);
         ui_set_colormap(conn->wnd, map);  
         // ui_destroy_colormap(map);  
449  }  }
450    
451  void process_update(HCONN conn, RDP_ORDER_STATE *os)  /* Send a synchronisation PDU */
452    static void
453    rdp_send_synchronise(void)
454  {  {
455          RDP_UPDATE_PDU update;          STREAM s;
456    
457          rdp_io_update_pdu(&conn->in, &update);          s = rdp_init_data(4);
458          switch (update.update_type)  
459          {          out_uint16_le(s, 1);    /* type */
460                  case RDP_UPDATE_ORDERS:          out_uint16_le(s, 1002);
                         process_orders(conn, os);  
                         break;  
                 case RDP_UPDATE_PALETTE:  
                         process_palette(conn);  
                         break;  
                 case RDP_UPDATE_SYNCHRONIZE:  
                         break;  
                 default:  
                         fprintf(stderr, "Unknown update 0x%x\n",  
                                 update.update_type);  
         }  
461    
462            s_mark_end(s);
463            rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
464  }  }
465    
466  void process_pointer(HCONN conn)  /* Send a single input event */
467    void
468    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
469  {  {
470          RDP_POINTER ptr;          STREAM s;
471    
472          rdp_io_pointer(&conn->in, &ptr);          s = rdp_init_data(16);
473    
474          switch (ptr.message)          out_uint16_le(s, 1);    /* number of events */
475          {          out_uint16(s, 0);       /* pad */
                 case RDP_POINTER_MOVE:  
                         ui_move_pointer(conn->wnd, ptr.x, ptr.y);  
                         break;  
                 default:  
                         fprintf(stderr, "Unknown pointer message 0x%x\n",  
                                 ptr.message);  
         }  
 }  
476    
477  /* Work this out later. This is useless anyway when encryption is off. */          out_uint32_le(s, time);
478  uint8 precanned_key_packet[] = {          out_uint16_le(s, message_type);
479     0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00,          out_uint16_le(s, device_flags);
480     0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x86,          out_uint16_le(s, param1);
481     0xf7,0x99,0xef,0x60,0xc4,0x49,0x52,0xd0,0xd8,0xea,0xb5,0x4f,0x58,0x19,          out_uint16_le(s, param2);
    0x52,0x2a,0x93,0x83,0x57,0x4f,0x4e,0x04,0xde,0x96,0x51,0xab,0x13,0x20,  
    0xd8,0xe5,0x00,0x00,0x00,0x00,0x00,0x00  
 };  
482    
483  /* Create an RC4 key and transfer it to the server */          s_mark_end(s);
484  void rdp_establish_key(HCONN conn)          rdp_send_data(s, RDP_DATA_PDU_INPUT);
 {  
         mcs_init_data(conn);  
         memcpy(conn->out.data + conn->out.offset, precanned_key_packet,  
                sizeof(precanned_key_packet));  
         conn->out.offset += sizeof(precanned_key_packet);  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 /* Horrible horrible certificate stuff. Work out later. */  
 uint8 precanned_cert_packet[] = {  
 0x80,0x00,0x00,0x00,0x12,0x02,0xb4,0x04,0x01,0x00,0x00,  
 0x00,0x00,0x00,0x01,0x02,0x9d,0xa3,0x7a,0x93,0x34,0x7b,0x28,0x37,0x24,0xa0,0x1f,  
 0x61,0x26,0xfd,0x96,0x3a,0x92,0x83,0xf3,0xe9,0x6a,0x2e,0x81,0x7c,0x2c,0xe4,0x72,//  
 0x01,0x18,0xe9,0xa1,0x0f,0x00,0x00,0x48,0x00,0x84,0x23,0x90,0xe6,0xd3,0xf8,0x20,  
 0xdb,0xa8,0x1b,0xb2,0xd0,0x78,0x2c,0x35,0xde,0xe3,0x0e,0x63,0x40,0xca,0xac,0x71,  
 0xc9,0x17,0x49,0x05,0x25,0xeb,0x9b,0xd0,0xa6,0x5c,0x90,0x3e,0x9d,0x4b,0x27,0x01,  
 0x79,0x1c,0x22,0xfb,0x3c,0x2c,0xb9,0x9f,0xf5,0x21,0xf3,0xee,0xd5,0x4d,0x47,0x1c,  
 0x85,0xbe,0x83,0x93,0xe8,0xed,0x8c,0x5c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x01,0x00,0x10,0x04,0x30,0x82,0x04,0x0c,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,  
 0x0d,0x01,0x07,0x02,0xa0,0x82,0x03,0xfd,0x30,0x82,0x03,0xf9,0x02,0x01,0x01,0x31,  
 0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,  
 0x03,0xe1,0x30,0x82,0x01,0x77,0x30,0x82,0x01,0x25,0xa0,0x03,0x02,0x01,0x02,0x02,  
 0x08,0x01,0xbf,0x06,0x84,0x9d,0xdb,0x2d,0xe0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,  
 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x30,0x38,0x31,0x36,0x30,0x11,0x06,0x03,  
 0x55,0x04,0x03,0x1e,0x0a,0x00,0x4e,0x00,0x54,0x00,0x54,0x00,0x53,0x00,0x45,0x30,  
 0x21,0x06,0x03,0x55,0x04,0x07,0x1e,0x1a,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,  
 0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,0x00,0x63,0x00,0x6f,  
 0x00,0x6d,0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x39,0x32,0x34,0x31,0x32,0x30,0x32,  
 0x30,0x34,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x31,0x32,0x30,0x32,0x30,  
 0x34,0x5a,0x30,0x38,0x31,0x36,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x1e,0x0a,0x00,  
 0x4e,0x00,0x54,0x00,0x54,0x00,0x53,0x00,0x45,0x30,0x21,0x06,0x03,0x55,0x04,0x07,  
 0x1e,0x1a,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,  
 0x00,0x66,0x00,0x74,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x30,0x5c,0x30,0x0d,  
 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,  
 0x30,0x48,0x02,0x41,0x00,0x91,0xb2,0x16,0x1c,0xae,0x4f,0x7f,0x7c,0xaf,0x57,0x2b,  
 0x23,0x4c,0x0c,0x25,0x3c,0x4f,0x66,0x9d,0x25,0xc3,0x4f,0x29,0xee,0x8b,0xda,0x4e,  
 0x95,0xe7,0x3b,0xaa,0xc0,0xa7,0xba,0xaf,0x99,0x8c,0x47,0x24,0x8b,0x09,0x77,0xbc,  
 0x2c,0xf4,0xe7,0x1a,0x07,0x58,0x7b,0x11,0x37,0x2a,0xa8,0x90,0xc3,0x50,0x92,0x80,  
 0x15,0xc5,0xda,0x51,0x8b,0x02,0x03,0x01,0x00,0x01,0xa3,0x13,0x30,0x11,0x30,0x0f,  
 0x06,0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x00,0x30,  
 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x41,0x00,0x14,0x04,0x67,  
 0x28,0xc8,0xd3,0x1f,0x13,0x14,0x2e,0x2c,0x93,0x09,0x25,0xbb,0xbe,0x86,0x6a,0xd3,  
 0x47,0x6f,0x44,0x16,0x7b,0x94,0x8c,0xb2,0xa2,0xd5,0xf7,0x4f,0xb1,0x8f,0x7f,0xde,  
 0x0b,0x88,0x34,0x4a,0x1d,0xdc,0xa1,0xfd,0x26,0xbd,0x43,0xbb,0x38,0xf1,0x87,0x34,  
 0xbb,0xe9,0x3b,0xfa,0x7f,0x1e,0xff,0xe1,0x10,0x7e,0xee,0x6e,0xd8,0x30,0x82,0x02,  
 0x62,0x30,0x82,0x02,0x10,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x01,0x00,0x00,0x00,  
 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x38,0x31,0x36,  
 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x1e,0x0a,0x00,0x4e,0x00,0x54,0x00,0x54,0x00,  
 0x53,0x00,0x45,0x30,0x21,0x06,0x03,0x55,0x04,0x07,0x1e,0x1a,0x00,0x4d,0x00,0x69,  
 0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,  
 0x00,0x63,0x00,0x6f,0x00,0x6d,0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x39,0x32,0x34,  
 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x30,  
 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x79,0x31,0x77,0x30,0x17,0x06,0x03,0x55,0x04,  
 0x03,0x1e,0x10,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x37,0x00,0x2d,0x00,0x4e,0x00,  
 0x45,0x00,0x57,0x30,0x17,0x06,0x03,0x55,0x04,0x07,0x1e,0x10,0x00,0x7a,0x00,0x32,  
 0x00,0x32,0x00,0x33,0x00,0x32,0x00,0x32,0x00,0x30,0x00,0x33,0x30,0x43,0x06,0x03,  
 0x55,0x04,0x05,0x1e,0x3c,0x00,0x31,0x00,0x42,0x00,0x63,0x00,0x4b,0x00,0x65,0x00,  
 0x57,0x00,0x50,0x00,0x6c,0x00,0x37,0x00,0x58,0x00,0x47,0x00,0x61,0x00,0x73,0x00,  
 0x38,0x00,0x4a,0x00,0x79,0x00,0x50,0x00,0x34,0x00,0x30,0x00,0x7a,0x00,0x49,0x00,  
 0x6d,0x00,0x6e,0x00,0x6f,0x00,0x51,0x00,0x5a,0x00,0x59,0x00,0x3d,0x00,0x0d,0x00,  
 0x0a,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,  
 0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0x91,0xb2,0x16,0x1c,0xae,0x4f,  
 0x7f,0x7c,0xaf,0x57,0x2b,0x23,0x4c,0x0c,0x25,0x3c,0x4f,0x66,0x9d,0x25,0xc3,0x4f,  
 0x29,0xee,0x8b,0xda,0x4e,0x95,0xe7,0x3b,0xaa,0xc0,0xa7,0xba,0xaf,0x99,0x8c,0x47,  
 0x24,0x8b,0x09,0x77,0xbc,0x2c,0xf4,0xe7,0x1a,0x07,0x58,0x7b,0x11,0x37,0x2a,0xa8,  
 0x90,0xc3,0x50,0x92,0x80,0x15,0xc5,0xda,0x51,0x8b,0x02,0x03,0x01,0x00,0x01,0xa3,  
 0x81,0xc3,0x30,0x81,0xc0,0x30,0x14,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,  
 0x12,0x04,0x01,0x01,0xff,0x04,0x04,0x01,0x00,0x01,0x00,0x30,0x3c,0x06,0x09,0x2b,  
 0x06,0x01,0x04,0x01,0x82,0x37,0x12,0x02,0x01,0x01,0xff,0x04,0x2c,0x4d,0x00,0x69,  
 0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,  
 0x00,0x43,0x00,0x6f,0x00,0x72,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x74,  
 0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x30,0x4c,0x06,0x09,0x2b,0x06,0x01,  
 0x04,0x01,0x82,0x37,0x12,0x05,0x01,0x01,0xff,0x04,0x3c,0x00,0x10,0x00,0x00,0x01,  
 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x18,0x00,0x18,0x00,0x30,  
 0x00,0x01,0x00,0x32,0x00,0x33,0x00,0x36,0x00,0x2d,0x00,0x34,0x00,0x2e,0x00,0x30,  
 0x00,0x30,0x00,0x2d,0x00,0x45,0x00,0x58,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x1c,0x06,0x03,0x55,0x1d,0x23,0x01,0x01,  
 0xff,0x04,0x12,0x30,0x10,0xa1,0x07,0x81,0x05,0x4e,0x54,0x54,0x53,0x45,0x82,0x05,  
 0x01,0x00,0x00,0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,  
 0x03,0x41,0x00,0x7b,0x1d,0xfd,0x24,0xea,0xf2,0xe8,0x17,0xdd,0x88,0x7e,0xfd,0xee,  
 0x28,0x61,0x7a,0x02,0xc3,0x73,0xcf,0x32,0x0f,0x7c,0x66,0x87,0x31,0xa7,0xbe,0x1b,  
 0x31,0xe2,0x20,0xa5,0x76,0x91,0x68,0x97,0x53,0x9e,0x80,0xcd,0x2b,0xd0,0x8e,0x8b,  
 0x7f,0x89,0x1b,0x62,0xa8,0xf8,0xee,0x5e,0x56,0xbd,0x9c,0x6b,0x80,0x06,0x54,0xd3,  
 0xf0,0xbf,0xb2,0x31,0x00,0x01,0x00,0x14,0x00,0xc7,0x32,0xf2,0x5b,0x98,0x0e,0x04,  
 0x49,0xa0,0x27,0x7e,0xf5,0xf6,0x0f,0xda,0x08,0x1d,0xe9,0x79,0xd1,0x31,0xc6,0x50,  
 0x90,0x4a,0xd3,0x1f,0x1d,0xf0,0x65,0x0d,0xb6,0x1f,0xaf,0xc9,0x1d  
 };  
   
 /* Send license certificate and related data to the server */  
 void rdp_send_cert(HCONN conn)  
 {  
         mcs_init_data(conn);  
         prs_io_uint8s(&conn->out, precanned_cert_packet, sizeof(precanned_cert_packet));  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
485  }  }
486    
487  /* Initialise RDP transport packet */  /* Inform the server on the contents of the persistent bitmap cache */
488  void rdp_init(HCONN conn)  static void
489    rdp_enum_bmpcache2(void)
490  {  {
491          mcs_init_data(conn);          STREAM s;
492          PUSH_LAYER(conn->out, rdp_offset, 6);          HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
493  }          uint32 num_keys, offset, count, flags;
494    
495  /* Transmit RDP transport packet */          offset = 0;
496  void rdp_send(HCONN conn, uint16 pdu_type)          num_keys = pstcache_enumerate(2, keylist);
 {  
         RDP_HEADER hdr;  
         int length;  
497    
498          POP_LAYER(conn->out, rdp_offset);          while (offset < num_keys)
499          length = conn->out.end - conn->out.offset;          {
500          rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);                  count = MIN(num_keys - offset, 169);
         rdp_io_header(&conn->out, &hdr);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
501    
502  /* Initialise RDP transport data packet */                  s = rdp_init_data(24 + count * sizeof(HASH_KEY));
 void rdp_init_data(HCONN conn)  
 {  
         mcs_init_data(conn);  
         PUSH_LAYER(conn->out, rdp_offset, 18);  
 }  
503    
504  /* Transmit RDP transport data packet */                  flags = 0;
505  void rdp_send_data(HCONN conn, uint16 data_pdu_type)                  if (offset == 0)
506  {                          flags |= PDU_FLAG_FIRST;
507          RDP_HEADER hdr;                  if (num_keys - offset <= 169)
508          RDP_DATA_HEADER datahdr;                          flags |= PDU_FLAG_LAST;
         int length = conn->out.end - conn->out.offset;  
509    
510          POP_LAYER(conn->out, rdp_offset);                  /* header */
511          length = conn->out.end - conn->out.offset;                  out_uint32_le(s, 0);
512          rdp_make_header(&hdr, length, RDP_PDU_DATA, conn->mcs_userid);                  out_uint16_le(s, count);
513          rdp_io_header(&conn->out, &hdr);                  out_uint16_le(s, 0);
514          rdp_make_data_header(&datahdr, 0x103ea, length, data_pdu_type);                  out_uint16_le(s, 0);
515          rdp_io_data_header(&conn->out, &datahdr);                  out_uint16_le(s, 0);
516          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);                  out_uint16_le(s, 0);
517                    out_uint16_le(s, num_keys);
518                    out_uint32_le(s, 0);
519                    out_uint32_le(s, flags);
520    
521                    /* list */
522                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
523    
524                    s_mark_end(s);
525                    rdp_send_data(s, 0x2b);
526    
527                    offset += 169;
528            }
529  }  }
530    
531  void rdp_send_confirm_active(HCONN conn)  /* Send an (empty) font information PDU */
532    static void
533    rdp_send_fonts(uint16 seq)
534  {  {
535          RDP_ACTIVE_PDU active;          STREAM s;
536    
537            s = rdp_init_data(8);
538    
539            out_uint16(s, 0);       /* number of fonts */
540            out_uint16_le(s, 0);    /* pad? */
541            out_uint16_le(s, seq);  /* unknown */
542            out_uint16_le(s, 0x32); /* entry size */
543    
544          rdp_init(conn);          s_mark_end(s);
545          rdp_make_active_pdu(&active, 0x103ea, conn->mcs_userid);          rdp_send_data(s, RDP_DATA_PDU_FONT2);
         rdp_io_active_pdu(&conn->out, &active, RDP_PDU_CONFIRM_ACTIVE);  
         MARK_END(conn->out);  
         rdp_send(conn, RDP_PDU_CONFIRM_ACTIVE);  
546  }  }
547    
548  void rdp_send_synchronize(HCONN conn)  /* Output general capability set */
549    static void
550    rdp_out_general_caps(STREAM s)
551  {  {
552          RDP_SYNCHRONIZE_PDU sync;          out_uint16_le(s, RDP_CAPSET_GENERAL);
553            out_uint16_le(s, RDP_CAPLEN_GENERAL);
554    
555          rdp_init_data(conn);          out_uint16_le(s, 1);    /* OS major type */
556          rdp_make_synchronize_pdu(&sync, 1002);          out_uint16_le(s, 3);    /* OS minor type */
557          rdp_io_synchronize_pdu(&conn->out, &sync);          out_uint16_le(s, 0x200);        /* Protocol version */
558          MARK_END(conn->out);          out_uint16(s, 0);       /* Pad */
559          rdp_send_data(conn, RDP_DATA_PDU_SYNCHRONIZE);          out_uint16(s, 0);       /* Compression types */
560            out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
561            /* Pad, according to T.128. 0x40d seems to
562               trigger
563               the server to start sending RDP5 packets.
564               However, the value is 0x1d04 with W2KTSK and
565               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
566               for sending such information in a padding
567               field.. */
568            out_uint16(s, 0);       /* Update capability */
569            out_uint16(s, 0);       /* Remote unshare capability */
570            out_uint16(s, 0);       /* Compression level */
571            out_uint16(s, 0);       /* Pad */
572  }  }
573    
574  void rdp_send_control(HCONN conn, uint16 action)  /* Output bitmap capability set */
575    static void
576    rdp_out_bitmap_caps(STREAM s)
577  {  {
578          RDP_CONTROL_PDU control;          out_uint16_le(s, RDP_CAPSET_BITMAP);
579            out_uint16_le(s, RDP_CAPLEN_BITMAP);
580    
581          rdp_init_data(conn);          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
582          rdp_make_control_pdu(&control, action);          out_uint16_le(s, 1);    /* Receive 1 BPP */
583          rdp_io_control_pdu(&conn->out, &control);          out_uint16_le(s, 1);    /* Receive 4 BPP */
584          MARK_END(conn->out);          out_uint16_le(s, 1);    /* Receive 8 BPP */
585          rdp_send_data(conn, RDP_DATA_PDU_CONTROL);          out_uint16_le(s, 800);  /* Desktop width */
586            out_uint16_le(s, 600);  /* Desktop height */
587            out_uint16(s, 0);       /* Pad */
588            out_uint16(s, 1);       /* Allow resize */
589            out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
590            out_uint16(s, 0);       /* Unknown */
591            out_uint16_le(s, 1);    /* Unknown */
592            out_uint16(s, 0);       /* Pad */
593  }  }
594    
595  void rdp_send_fonts(HCONN conn, uint16 seqno)  /* Output order capability set */
596    static void
597    rdp_out_order_caps(STREAM s)
598  {  {
599          RDP_FONT_PDU fonts;          uint8 order_caps[32];
600    
601          rdp_init_data(conn);          memset(order_caps, 0, 32);
602          rdp_make_font_pdu(&fonts, seqno);          order_caps[0] = 1;      /* dest blt */
603          rdp_io_font_pdu(&conn->out, &fonts);          order_caps[1] = 1;      /* pat blt */
604          MARK_END(conn->out);          order_caps[2] = 1;      /* screen blt */
605          rdp_send_data(conn, RDP_DATA_PDU_FONT2);          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
606            order_caps[4] = 0;      /* triblt */
607            order_caps[8] = 1;      /* line */
608            order_caps[9] = 1;      /* line */
609            order_caps[10] = 1;     /* rect */
610            order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
611            order_caps[13] = 1;     /* memblt */
612            order_caps[14] = 1;     /* triblt */
613            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
614            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
615            order_caps[22] = 1;     /* polyline */
616            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
617            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
618            order_caps[27] = 1;     /* text2 */
619            out_uint16_le(s, RDP_CAPSET_ORDER);
620            out_uint16_le(s, RDP_CAPLEN_ORDER);
621    
622            out_uint8s(s, 20);      /* Terminal desc, pad */
623            out_uint16_le(s, 1);    /* Cache X granularity */
624            out_uint16_le(s, 20);   /* Cache Y granularity */
625            out_uint16(s, 0);       /* Pad */
626            out_uint16_le(s, 1);    /* Max order level */
627            out_uint16_le(s, 0x147);        /* Number of fonts */
628            out_uint16_le(s, 0x2a); /* Capability flags */
629            out_uint8p(s, order_caps, 32);  /* Orders supported */
630            out_uint16_le(s, 0x6a1);        /* Text capability flags */
631            out_uint8s(s, 6);       /* Pad */
632            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
633            out_uint32(s, 0);       /* Unknown */
634            out_uint32_le(s, 0x4e4);        /* Unknown */
635  }  }
636    
637  void rdp_send_input(HCONN conn)  /* Output bitmap cache capability set */
638    static void
639    rdp_out_bmpcache_caps(STREAM s)
640  {  {
641          RDP_INPUT_PDU input;          int Bpp;
642            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
643            out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
644    
645          rdp_init_data(conn);          Bpp = (g_server_bpp + 7) / 8;
646          rdp_make_input_pdu(&input);          out_uint8s(s, 24);      /* unused */
647          rdp_io_input_pdu(&conn->out, &input);          out_uint16_le(s, 0x258);        /* entries */
648          MARK_END(conn->out);          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
649          rdp_send_data(conn, RDP_DATA_PDU_INPUT);          out_uint16_le(s, 0x12c);        /* entries */
650            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
651            out_uint16_le(s, 0x106);        /* entries */
652            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
653  }  }
654    
655  BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  /* Output bitmap cache v2 capability set */
656    static void
657    rdp_out_bmpcache2_caps(STREAM s)
658  {  {
659          RDP_HEADER hdr;          out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
660            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
661    
662            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
663    
664          conn->in.offset = conn->in.rdp_offset;          out_uint16_le(s, 0x0300);       /* flags? number of caches? */
665    
666          if (conn->in.offset >= conn->in.end)          out_uint32_le(s, BMPCACHE2_C0_CELLS);
667            out_uint32_le(s, BMPCACHE2_C1_CELLS);
668            if (pstcache_init(2))
669          {          {
670                  if (!mcs_recv(conn, False))                  out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
                         return False;  
671          }          }
672            else
673          if (!rdp_io_header(&conn->in, &hdr))          {
674                  return False;                  out_uint32_le(s, BMPCACHE2_C2_CELLS);
675            }
676          conn->in.rdp_offset += hdr.length;          out_uint8s(s, 20);      /* other bitmap caches not used */
         *type = hdr.pdu_type & 0xf;  
   
 #if DEBUG  
         fprintf(stderr, "RDP packet (type %x):\n", *type);  
         dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset);  
 #endif  
   
         return True;  
677  }  }
678    
679  /* Disconnect from the RDP layer */  /* Output control capability set */
680  void rdp_disconnect(HCONN conn)  static void
681    rdp_out_control_caps(STREAM s)
682  {  {
683          mcs_disconnect(conn);          out_uint16_le(s, RDP_CAPSET_CONTROL);
684  }          out_uint16_le(s, RDP_CAPLEN_CONTROL);
685    
686  void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,          out_uint16(s, 0);       /* Control capabilities */
687                       uint16 userid)          out_uint16(s, 0);       /* Remote detach */
688  {          out_uint16_le(s, 2);    /* Control interest */
689          hdr->length = length;          out_uint16_le(s, 2);    /* Detach interest */
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
690  }  }
691    
692  void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,  /* Output activation capability set */
693                            uint16 length, uint16 data_pdu_type)  static void
694    rdp_out_activate_caps(STREAM s)
695  {  {
696          hdr->shareid = shareid;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
697          hdr->pad = 0;          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
         hdr->streamid = 1;  
         hdr->length = length - 14;  
         hdr->data_pdu_type = data_pdu_type;  
         hdr->compress_type = 0;  
         hdr->compress_len = 0;  
 }  
698    
699  void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)          out_uint16(s, 0);       /* Help key */
700  {          out_uint16(s, 0);       /* Help index key */
701          caps->os_major_type = 1;          out_uint16(s, 0);       /* Extended help key */
702          caps->os_minor_type = 3;          out_uint16(s, 0);       /* Window activate */
         caps->ver_protocol = 0x200;  
703  }  }
704    
705  void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps)  /* Output pointer capability set */
706    static void
707    rdp_out_pointer_caps(STREAM s)
708  {  {
709          caps->preferred_bpp = 8;          out_uint16_le(s, RDP_CAPSET_POINTER);
710          caps->receive1bpp = 1;          out_uint16_le(s, RDP_CAPLEN_POINTER);
711          caps->receive4bpp = 1;  
712          caps->receive8bpp = 1;          out_uint16(s, 0);       /* Colour pointer */
713          caps->width = 640;          out_uint16_le(s, 20);   /* Cache size */
         caps->height = 480;  
         caps->compression = 1;  
         caps->unknown2 = 1;  
714  }  }
715    
716  void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  /* Output share capability set */
717    static void
718    rdp_out_share_caps(STREAM s)
719  {  {
720          caps->xgranularity = 1;          out_uint16_le(s, RDP_CAPSET_SHARE);
721          caps->ygranularity = 20;          out_uint16_le(s, RDP_CAPLEN_SHARE);
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
   
 //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;  
722    
723          caps->support[0] = caps->support[1] = caps->support[2]          out_uint16(s, 0);       /* userid */
724                  = caps->support[3] = caps->support[4] = caps->support[5]          out_uint16(s, 0);       /* pad */
                 = caps->support[6] = caps->support[8] = caps->support[11]  
                 = caps->support[12] = caps->support[22] = caps->support[28]  
                 = caps->support[29] = caps->support[30] = 1;  
         caps->text_cap_flags = 0x6A1;  
         caps->desk_save_size = 0x38400;  
         caps->unknown2 = 0x4E4;  
725  }  }
726    
727  void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  /* Output colour cache capability set */
728    static void
729    rdp_out_colcache_caps(STREAM s)
730  {  {
731          caps->caches[0].entries = 0x258;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
732          caps->caches[0].max_cell_size = 0x100;          out_uint16_le(s, RDP_CAPLEN_COLCACHE);
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
 }  
733    
734  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)          out_uint16_le(s, 6);    /* cache size */
735  {          out_uint16(s, 0);       /* pad */
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
736  }  }
737    
738  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  static uint8 caps_0x0d[] = {
739  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
740  }          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
741            0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
742            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
743            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
744            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
745            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
746            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
748            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
749            0x00, 0x00, 0x00, 0x00
750    };
751    
752  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
 {  
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
753    
754  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
 {  
 }  
755    
756  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  static uint8 caps_0x10[] = {
757  {          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
758          caps->cache_size = 6;          0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
759  }          0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
760            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
761            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
762            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
763    };
764    
765  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid)  /* Output unknown capability sets */
766    static void
767    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
768  {  {
769          memset(pdu, 0, sizeof(*pdu));          out_uint16_le(s, id);
770          pdu->shareid = shareid;          out_uint16_le(s, length);
         pdu->userid  = 1002;  
         pdu->source_len = sizeof(RDP_SOURCE);  
         memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));  
771    
772          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          out_uint8p(s, caps, length - 4);
                 + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE  
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
   
         rdp_make_general_caps (&pdu->general_caps );  
         rdp_make_bitmap_caps  (&pdu->bitmap_caps  );  
         rdp_make_order_caps   (&pdu->order_caps   );  
         rdp_make_bmpcache_caps(&pdu->bmpcache_caps);  
         rdp_make_control_caps (&pdu->control_caps );  
         rdp_make_activate_caps(&pdu->activate_caps);  
         rdp_make_pointer_caps (&pdu->pointer_caps );  
         rdp_make_share_caps   (&pdu->share_caps, userid);  
         rdp_make_colcache_caps(&pdu->colcache_caps);  
773  }  }
774    
775  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  #define RDP5_FLAG 0x0030
776    /* Send a confirm active PDU */
777    static void
778    rdp_send_confirm_active(void)
779  {  {
780          pdu->action = action;          STREAM s;
781          pdu->userid = 0;          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
782          pdu->controlid = 0;          uint16 caplen =
783  }                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
784                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
785                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
786                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
787                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
788                    4 /* w2k fix, why? */ ;
789    
790  void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid)          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
 {  
         pdu->type = 1;  
         pdu->userid = userid;  
 }  
791    
792  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
793  {          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
794          pdu->num_fonts = 0;          out_uint16_le(s, (g_mcs_userid + 1001));
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
 }  
795    
796  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu)          out_uint32_le(s, g_rdp_shareid);
797  {          out_uint16_le(s, 0x3ea);        /* userid */
798          uint32 now = time(NULL);          out_uint16_le(s, sizeof(RDP_SOURCE));
799            out_uint16_le(s, caplen);
800    
801          pdu->num_events = 3;          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
802          pdu->pad = 0;          out_uint16_le(s, 0xd);  /* num_caps */
803            out_uint8s(s, 2);       /* pad */
804    
805          pdu->event[0].event_time = now;          rdp_out_general_caps(s);
806          pdu->event[0].message_type = RDP_INPUT_SYNCHRONIZE;          rdp_out_bitmap_caps(s);
807          pdu->event[0].device_flags = 0;          rdp_out_order_caps(s);
808          pdu->event[0].mouse_x = 0;          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
809          pdu->event[0].mouse_y = 0;          rdp_out_colcache_caps(s);
810            rdp_out_activate_caps(s);
811            rdp_out_control_caps(s);
812            rdp_out_pointer_caps(s);
813            rdp_out_share_caps(s);
814    
815          pdu->event[1].event_time = now;          rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
816          pdu->event[1].message_type = RDP_INPUT_UNKNOWN;          rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
817          pdu->event[1].device_flags = 0x8000;          rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
818          pdu->event[1].mouse_x = 15;          rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
         pdu->event[1].mouse_y = 0;  
819    
820          pdu->event[2].event_time = now;          s_mark_end(s);
821          pdu->event[2].message_type = RDP_INPUT_MOUSE;          sec_send(s, sec_flags);
         pdu->event[2].device_flags = MOUSE_FLAG_MOVE;  
         pdu->event[2].mouse_x = 425;  
         pdu->event[2].mouse_y = 493;  
822  }  }
823    
824  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  /* Process a general capability set */
825    static void
826    rdp_process_general_caps(STREAM s)
827  {  {
828          BOOL res = True;          uint16 pad2octetsB;     /* rdp5 flags? */
829    
830          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          in_uint8s(s, 10);
831          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          in_uint16_le(s, pad2octetsB);
         res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;  
832    
833          return res;          if (!pad2octetsB)
834                    g_use_rdp5 = False;
835  }  }
836    
837  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)  /* Process a bitmap capability set */
838    static void
839    rdp_process_bitmap_caps(STREAM s)
840  {  {
841          BOOL res = True;          uint16 width, height, bpp;
842    
843          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;          in_uint16_le(s, bpp);
844          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;          in_uint8s(s, 6);
         res = res ? prs_io_uint8 (s, &hdr->streamid     ) : False;  
         res = res ? lsb_io_uint16(s, &hdr->length       ) : False;  
         res = res ? prs_io_uint8 (s, &hdr->data_pdu_type) : False;  
         res = res ? prs_io_uint8 (s, &hdr->compress_type) : False;  
         res = res ? lsb_io_uint16(s, &hdr->compress_len ) : False;  
845    
846          return res;          in_uint16_le(s, width);
847  }          in_uint16_le(s, height);
848    
849  BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
 {  
         uint8 change;  
         BOOL res;  
850    
851          if (delta)          /*
852             * The server may limit bpp and change the size of the desktop (for
853             * example when shadowing another session).
854             */
855            if (g_server_bpp != bpp)
856          {          {
857                  res = prs_io_uint8(s, &change);                  warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
858                  *coord += change;                  g_server_bpp = bpp;
859          }          }
860          else          if (g_width != width || g_height != height)
861          {          {
862                  res = lsb_io_uint16(s, coord);                  warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
863                            width, height);
864                    g_width = width;
865                    g_height = height;
866                    ui_resize_window();
867          }          }
   
         return res;  
868  }  }
869    
870  BOOL rdp_io_colormap(STREAM s, COLORMAP *colors)  /* Process server capabilities */
871    void
872    rdp_process_server_caps(STREAM s, uint16 length)
873  {  {
874          int datasize;          int n;
875            uint8 *next, *start;
876          lsb_io_uint16(s, &colors->ncolors);          uint16 ncapsets, capset_type, capset_length;
         datasize = colors->ncolors * 3;  
   
         if (datasize > sizeof(colors->colors))  
                 return False;  
877    
878          memcpy(colors->colors, s->data + s->offset, datasize);          start = s->p;
         s->offset += datasize;  
         return True;  
 }  
879    
880  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)          in_uint16_le(s, ncapsets);
881  {          in_uint8s(s, 2);        /* pad */
         uint16 length = RDP_CAPLEN_GENERAL;  
         uint16 pkt_length = length;  
         BOOL res;  
882    
883          res = lsb_io_uint16(s, &pkt_length);          for (n = 0; n < ncapsets; n++)
         if (pkt_length != length)  
884          {          {
885                  fprintf(stderr, "Unrecognised capabilities size\n");                  if (s->p > start + length)
886                  return False;                          return;
         }  
   
         res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_types) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_update    ) : False;  
         res = res ? lsb_io_uint16(s, &caps->remote_unshare) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_level) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3          ) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BITMAP;  
         uint16 pkt_length = length;  
         BOOL res;  
887    
888          res = lsb_io_uint16(s, &pkt_length);                  in_uint16_le(s, capset_type);
889          if (pkt_length != length)                  in_uint16_le(s, capset_length);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
890    
891          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  next = s->p + capset_length - 4;
         res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->width        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->height       ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->allow_resize ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compression  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown1     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown2     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2         ) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_ORDER;  
         uint16 pkt_length = length;  
         BOOL res;  
892    
893          res = lsb_io_uint16(s, &pkt_length);                  switch (capset_type)
894          if (pkt_length != length)                  {
895          {                          case RDP_CAPSET_GENERAL:
896                  fprintf(stderr, "Unrecognised capabilities size\n");                                  rdp_process_general_caps(s);
897                  return False;                                  break;
         }  
898    
899          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;                          case RDP_CAPSET_BITMAP:
900          res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;                                  rdp_process_bitmap_caps(s);
901          res = res ? lsb_io_uint16(s, &caps->xgranularity     ) : False;                                  break;
902          res = res ? lsb_io_uint16(s, &caps->ygranularity     ) : False;                  }
         res = res ? lsb_io_uint16(s, &caps->pad2             ) : False;  
         res = res ? lsb_io_uint16(s, &caps->max_order_level  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->num_fonts        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_flags        ) : False;  
         res = res ? prs_io_uint8s(s,  caps->support      , 32) : False;  
         res = res ? lsb_io_uint16(s, &caps->text_cap_flags   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->pad4             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->desk_save_size   ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown1         ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown2         ) : False;  
903    
904          return res;                  s->p = next;
905            }
906  }  }
907    
908  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  /* Respond to a demand active PDU */
909    static void
910    process_demand_active(STREAM s)
911  {  {
912          if (!lsb_io_uint16(s, &info->entries      ))          uint8 type;
913                  return False;          uint16 len_src_descriptor, len_combined_caps;
   
         if (!lsb_io_uint16(s, &info->max_cell_size))  
                 return False;  
   
         return True;  
 }  
914    
915  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)          in_uint32_le(s, g_rdp_shareid);
916  {          in_uint16_le(s, len_src_descriptor);
917          uint16 length = RDP_CAPLEN_BMPCACHE;          in_uint16_le(s, len_combined_caps);
918          uint16 pkt_length = length;          in_uint8s(s, len_src_descriptor);
919          BOOL res;  
920          int i;          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
921            rdp_process_server_caps(s, len_combined_caps);
922    
923            rdp_send_confirm_active();
924            rdp_send_synchronise();
925            rdp_send_control(RDP_CTL_COOPERATE);
926            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
927            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
928            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
929            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
930            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
931    
932          res = lsb_io_uint16(s, &pkt_length);          if (g_use_rdp5)
         if (pkt_length != length)  
933          {          {
934                  fprintf(stderr, "Unrecognised capabilities size\n");                  rdp_enum_bmpcache2();
935                  return False;                  rdp_send_fonts(3);
936            }
937            else
938            {
939                    rdp_send_fonts(1);
940                    rdp_send_fonts(2);
941          }          }
942    
943          for (i = 0; i < 6; i++)          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
944                  res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;          reset_order_state();
   
         for (i = 0; i < 3; i++)  
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
   
         return res;  
945  }  }
946    
947  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  /* Process a colour pointer PDU */
948    void
949    process_colour_pointer_pdu(STREAM s)
950  {  {
951          uint16 length = RDP_CAPLEN_CONTROL;          uint16 x, y, width, height, cache_idx, masklen, datalen;
952          uint16 pkt_length = length;          uint8 *mask, *data;
953          BOOL res;          HCURSOR cursor;
954    
955          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, cache_idx);
956          if (pkt_length != length)          in_uint16_le(s, x);
957          {          in_uint16_le(s, y);
958                  fprintf(stderr, "Unrecognised capabilities size\n");          in_uint16_le(s, width);
959                  return False;          in_uint16_le(s, height);
960          }          in_uint16_le(s, masklen);
961            in_uint16_le(s, datalen);
962            in_uint8p(s, data, datalen);
963            in_uint8p(s, mask, masklen);
964            cursor = ui_create_cursor(x, y, width, height, mask, data);
965            ui_set_cursor(cursor);
966            cache_put_cursor(cache_idx, cursor);
967    }
968    
969          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;  /* Process a cached pointer PDU */
970          res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;  void
971          res = res ? lsb_io_uint16(s, &caps->control_interest) : False;  process_cached_pointer_pdu(STREAM s)
972          res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  {
973            uint16 cache_idx;
974    
975          return res;          in_uint16_le(s, cache_idx);
976            ui_set_cursor(cache_get_cursor(cache_idx));
977  }  }
978    
979  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  /* Process a system pointer PDU */
980    void
981    process_system_pointer_pdu(STREAM s)
982  {  {
983          uint16 length = RDP_CAPLEN_ACTIVATE;          uint16 system_pointer_type;
         uint16 pkt_length = length;  
         BOOL res;  
984    
985          res = lsb_io_uint16(s, &pkt_length);          in_uint16(s, system_pointer_type);
986          if (pkt_length != length)          switch (system_pointer_type)
987          {          {
988                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_NULL_POINTER:
989                  return False;                          ui_set_null_cursor();
990          }                          break;
   
         res = res ? lsb_io_uint16(s, &caps->help_key         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_index_key   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_extended_key) : False;  
         res = res ? lsb_io_uint16(s, &caps->window_activate  ) : False;  
991    
992          return res;                  default:
993                            unimpl("System pointer message 0x%x\n", system_pointer_type);
994            }
995  }  }
996    
997  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  /* Process a pointer PDU */
998    static void
999    process_pointer_pdu(STREAM s)
1000  {  {
1001          uint16 length = RDP_CAPLEN_POINTER;          uint16 message_type;
1002          uint16 pkt_length = length;          uint16 x, y;
         BOOL res;  
1003    
1004          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, message_type);
1005          if (pkt_length != length)          in_uint8s(s, 2);        /* pad */
1006    
1007            switch (message_type)
1008          {          {
1009                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_POINTER_MOVE:
1010                  return False;                          in_uint16_le(s, x);
1011          }                          in_uint16_le(s, y);
1012                            if (s_check(s))
1013                                    ui_move_pointer(x, y);
1014                            break;
1015    
1016          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_POINTER_COLOR:
1017          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          process_colour_pointer_pdu(s);
1018                            break;
1019    
1020          return res;                  case RDP_POINTER_CACHED:
1021  }                          process_cached_pointer_pdu(s);
1022                            break;
1023    
1024  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                  case RDP_POINTER_SYSTEM:
1025  {                          process_system_pointer_pdu(s);
1026          uint16 length = RDP_CAPLEN_SHARE;                          break;
         uint16 pkt_length = length;  
         BOOL res;  
1027    
1028          res = lsb_io_uint16(s, &pkt_length);                  default:
1029          if (pkt_length != length)                          unimpl("Pointer message 0x%x\n", message_type);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
1030          }          }
   
         res = res ? lsb_io_uint16(s, &caps->userid) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad   ) : False;  
   
         return res;  
1031  }  }
1032    
1033  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  /* Process bitmap updates */
1034    void
1035    process_bitmap_updates(STREAM s)
1036  {  {
1037          uint16 length = RDP_CAPLEN_COLCACHE;          uint16 num_updates;
1038          uint16 pkt_length = length;          uint16 left, top, right, bottom, width, height;
1039          BOOL res;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1040            uint8 *data, *bmpdata;
1041            int i;
1042    
1043          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, num_updates);
         if (pkt_length != length)  
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
1044    
1045          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          for (i = 0; i < num_updates; i++)
1046          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          {
1047                    in_uint16_le(s, left);
1048                    in_uint16_le(s, top);
1049                    in_uint16_le(s, right);
1050                    in_uint16_le(s, bottom);
1051                    in_uint16_le(s, width);
1052                    in_uint16_le(s, height);
1053                    in_uint16_le(s, bpp);
1054                    Bpp = (bpp + 7) / 8;
1055                    in_uint16_le(s, compress);
1056                    in_uint16_le(s, bufsize);
1057    
1058          return res;                  cx = right - left + 1;
1059  }                  cy = bottom - top + 1;
1060    
1061  uint8 canned_caps[] = {                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1062  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,                         left, top, right, bottom, width, height, Bpp, compress));
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x01,  
 0x00,0x00,0x00,0x0E,0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x34,0x00,0xFE,  
 0x00,0x04,0x00,0xFE,0x00,0x04,0x00,0xFE,0x00,0x08,0x00,0xFE,0x00,0x08,0x00,0xFE,  
 0x00,0x10,0x00,0xFE,0x00,0x20,0x00,0xFE,0x00,0x40,0x00,0xFE,0x00,0x80,0x00,0xFE,  
 0x00,0x00,0x01,0x40,0x00,0x00,0x08,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00  
 };  
1063    
1064  BOOL rdp_io_unknown_caps(STREAM s, void *caps)                  if (!compress)
1065  {                  {
1066          uint16 length = 0x58;                          int y;
1067          uint16 pkt_length = length;                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1068          BOOL res;                          for (y = 0; y < height; y++)
1069                            {
1070                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1071                                              width * Bpp);
1072                            }
1073                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1074                            xfree(bmpdata);
1075                            continue;
1076                    }
1077    
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
1078    
1079          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;                  if (compress & 0x400)
1080                    {
1081                            size = bufsize;
1082                    }
1083                    else
1084                    {
1085                            in_uint8s(s, 2);        /* pad */
1086                            in_uint16_le(s, size);
1087                            in_uint8s(s, 4);        /* line_size, final_size */
1088                    }
1089                    in_uint8p(s, data, size);
1090                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1091                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1092                    {
1093                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1094                    }
1095                    else
1096                    {
1097                            DEBUG_RDP5(("Failed to decompress data\n"));
1098                    }
1099    
1100          return res;                  xfree(bmpdata);
1101            }
1102  }  }
1103    
1104  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  /* Process a palette update */
1105    void
1106    process_palette(STREAM s)
1107  {  {
1108          uint16 capset;          COLOURENTRY *entry;
1109          uint16 length;          COLOURMAP map;
1110          BOOL res;          HCOLOURMAP hmap;
1111          int i;          int i;
1112    
1113          res = lsb_io_uint32(s, &pdu->shareid);          in_uint8s(s, 2);        /* pad */
1114            in_uint16_le(s, map.ncolours);
1115            in_uint8s(s, 2);        /* pad */
1116    
1117          if (pdutype == RDP_PDU_CONFIRM_ACTIVE)          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
1118    
1119          res = res ? lsb_io_uint16(s, &pdu->source_len) : False;          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
1120    
1121          if (pdu->source_len > 48)          for (i = 0; i < map.ncolours; i++)
1122          {          {
1123                  fprintf(stderr, "RDP source descriptor too long\n");                  entry = &map.colours[i];
1124                  return False;                  in_uint8(s, entry->red);
1125                    in_uint8(s, entry->green);
1126                    in_uint8(s, entry->blue);
1127          }          }
1128    
1129          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          hmap = ui_create_colourmap(&map);
1130          res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;          ui_set_colourmap(hmap);
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
   
         if (s->marshall)  
         {  
                 capset = RDP_CAPSET_GENERAL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_general_caps(s, &pdu->general_caps) : False;  
   
                 capset = RDP_CAPSET_BITMAP;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bitmap_caps (s, &pdu->bitmap_caps ) : False;  
   
                 capset = RDP_CAPSET_ORDER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_order_caps  (s, &pdu->order_caps  ) : False;  
   
                 capset = RDP_CAPSET_BMPCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps) : False;  
   
                 capset = RDP_CAPSET_COLCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_colcache_caps(s, &pdu->colcache_caps) : False;  
   
                 capset = RDP_CAPSET_ACTIVATE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_activate_caps(s, &pdu->activate_caps) : False;  
   
                 capset = RDP_CAPSET_CONTROL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_control_caps(s, &pdu->control_caps) : False;  
   
                 capset = RDP_CAPSET_POINTER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_pointer_caps(s, &pdu->pointer_caps) : False;  
   
                 capset = RDP_CAPSET_SHARE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_share_caps  (s, &pdu->share_caps  ) : False;  
   
                 capset = RDP_CAPSET_UNKNOWN;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_unknown_caps(s, NULL) : False;  
         }  
         else  
         {  
                 for (i = 0; i < pdu->num_caps; i++)  
                 {  
                         if (!res)  
                                 return False;  
1131    
1132                          if (!lsb_io_uint16(s, &capset))          xfree(map.colours);
1133                                  return False;  }
1134    
1135                          switch (capset)  /* Process an update PDU */
1136                          {  static void
1137                          case RDP_CAPSET_GENERAL:  process_update_pdu(STREAM s)
1138                                  res = rdp_io_general_caps (s, &pdu->general_caps );  {
1139                                  break;          uint16 update_type, count;
                         case RDP_CAPSET_BITMAP:  
                                 res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );  
                                 break;  
                         case RDP_CAPSET_ORDER:  
                                 res = rdp_io_order_caps   (s, &pdu->order_caps   );  
                                 break;  
                         case RDP_CAPSET_BMPCACHE:  
                                 res = rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps);  
                                 break;  
                         case RDP_CAPSET_CONTROL:  
                                 res = rdp_io_control_caps (s, &pdu->control_caps );  
                                 break;  
                         case RDP_CAPSET_ACTIVATE:  
                                 res = rdp_io_activate_caps(s, &pdu->activate_caps);  
                                 break;  
                         case RDP_CAPSET_POINTER:  
                                 res = rdp_io_pointer_caps (s, &pdu->pointer_caps );  
                                 break;  
                         case RDP_CAPSET_SHARE:  
                                 res = rdp_io_share_caps   (s, &pdu->share_caps   );  
                                 break;  
                         case RDP_CAPSET_COLCACHE:  
                                 res = rdp_io_colcache_caps(s, &pdu->colcache_caps);  
                                 break;  
                         default:  
                                 fprintf(stderr, "Warning: Unrecognised capset %x\n",  
                                         capset);  
1140    
1141                                  if (!lsb_io_uint16(s, &length))          in_uint16_le(s, update_type);
                                         return False;  
1142    
1143                                  s->offset += (length - 4);          ui_begin_update();
1144                          }          switch (update_type)
1145                  }          {
1146          }                  case RDP_UPDATE_ORDERS:
1147                            in_uint8s(s, 2);        /* pad */
1148                            in_uint16_le(s, count);
1149                            in_uint8s(s, 2);        /* pad */
1150                            process_orders(s, count);
1151                            break;
1152    
1153          return res;                  case RDP_UPDATE_BITMAP:
1154  }                          process_bitmap_updates(s);
1155                            break;
1156    
1157  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)                  case RDP_UPDATE_PALETTE:
1158  {                          process_palette(s);
1159          BOOL res = True;                          break;
1160    
1161          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;                  case RDP_UPDATE_SYNCHRONIZE:
1162          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;                          break;
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
1163    
1164          return res;                  default:
1165                            unimpl("update %d\n", update_type);
1166            }
1167            ui_end_update();
1168  }  }
1169    
1170  BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu)  /* Process a disconnect PDU */
1171    void
1172    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1173  {  {
1174          BOOL res = True;          in_uint32_le(s, *ext_disc_reason);
1175    
1176          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          DEBUG(("Received disconnect PDU\n"));
         res = res ? lsb_io_uint16(s, &pdu->userid) : False;  
   
         return res;  
1177  }  }
1178    
1179  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  /* Process data PDU */
1180    static BOOL
1181    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1182  {  {
1183          BOOL res = True;          uint8 data_pdu_type;
1184            uint8 ctype;
1185            uint16 clen;
1186            uint32 len;
1187    
1188          res = res ? lsb_io_uint32(s, &evt->event_time)   : False;          uint32 roff, rlen;
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
1189    
1190          if (!res)          struct stream *ns = &(g_mppc_dict.ns);
1191                  return False;  
1192            in_uint8s(s, 6);        /* shareid, pad, streamid */
1193            in_uint16(s, len);
1194            in_uint8(s, data_pdu_type);
1195            in_uint8(s, ctype);
1196            in_uint16(s, clen);
1197            clen -= 18;
1198    
1199          switch (evt->message_type)          if (ctype & RDP_MPPC_COMPRESSED)
1200          {          {
1201          case RDP_INPUT_CODEPOINT:                  if (len > RDP_MPPC_DICT_SIZE)
1202          case RDP_INPUT_VIRTKEY:                          error("error decompressed packet size exceeds max\n");
1203                  res = res ? lsb_io_uint16(s, &evt->device_flags) : False;                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1204                  res = res ? lsb_io_uint16(s, &evt->kbd_keycode ) : False;                          error("error while decompressing packet\n");
                 break;  
         case RDP_INPUT_SYNCHRONIZE:  
         case RDP_INPUT_UNKNOWN:  
         case RDP_INPUT_MOUSE:  
                 res = res ? lsb_io_uint16(s, &evt->device_flags) : False;  
                 res = res ? lsb_io_uint16(s, &evt->mouse_x     ) : False;  
                 res = res ? lsb_io_uint16(s, &evt->mouse_y     ) : False;  
                 break;  
         default:  
                 fprintf(stderr, "Unknown input type %d\n", evt->message_type);  
                 return False;  
         }  
1205    
1206          return res;                  /* len -= 18; */
 }  
1207    
1208  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)                  /* allocate memory and copy the uncompressed data into the temporary stream */
1209  {                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
         BOOL res = True;  
         int i;  
1210    
1211          res = res ? lsb_io_uint16(s, &pdu->num_events) : False;                  memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
1212    
1213          if (pdu->num_events > RDP_MAX_EVENTS)                  ns->size = rlen;
1214          {                  ns->end = (ns->data + ns->size);
1215                  fprintf(stderr, "Too many events in one PDU\n");                  ns->p = ns->data;
1216                  return False;                  ns->rdp_hdr = ns->p;
         }  
1217    
1218          for (i = 0; i < pdu->num_events; i++)                  s = ns;
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
1219          }          }
1220    
1221          return res;          switch (data_pdu_type)
1222  }          {
1223                    case RDP_DATA_PDU_UPDATE:
1224                            process_update_pdu(s);
1225                            break;
1226    
1227  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)                  case RDP_DATA_PDU_CONTROL:
1228  {                          DEBUG(("Received Control PDU\n"));
1229          BOOL res = True;                          break;
1230    
1231          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;                  case RDP_DATA_PDU_SYNCHRONISE:
1232          res = res ? lsb_io_uint16(s, &font->flags    ) : False;                          DEBUG(("Received Sync PDU\n"));
1233          res = res ? lsb_io_uint16(s, &font->width    ) : False;                          break;
         res = res ? lsb_io_uint16(s, &font->height   ) : False;  
         res = res ? lsb_io_uint16(s, &font->xaspect  ) : False;  
         res = res ? lsb_io_uint16(s, &font->yaspect  ) : False;  
         res = res ? lsb_io_uint32(s, &font->signature) : False;  
         res = res ? lsb_io_uint16(s, &font->codepage ) : False;  
         res = res ? lsb_io_uint16(s, &font->ascent   ) : False;  
1234    
1235          return res;                  case RDP_DATA_PDU_POINTER:
1236  }                          process_pointer_pdu(s);
1237                            break;
1238    
1239  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)                  case RDP_DATA_PDU_BELL:
1240  {                          ui_bell();
1241          BOOL res = True;                          break;
         int i;  
1242    
1243          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;                  case RDP_DATA_PDU_LOGON:
1244          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;                          DEBUG(("Received Logon PDU\n"));
1245          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;                          /* User logged on */
1246          res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;                          break;
1247    
1248          if (pdu->num_fonts > RDP_MAX_FONTS)                  case RDP_DATA_PDU_DISCONNECT:
1249          {                          process_disconnect_pdu(s, ext_disc_reason);
1250                  fprintf(stderr, "Too many fonts in one PDU\n");                          return True;
                 return False;  
         }  
1251    
1252          for (i = 0; i < pdu->num_fonts; i++)                  default:
1253          {                          unimpl("data PDU %d\n", data_pdu_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
1254          }          }
1255            return False;
         return res;  
1256  }  }
1257    
1258  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  /* Process incoming packets */
1259    /* nevers gets out of here till app is done */
1260    void
1261    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1262  {  {
1263          BOOL res = True;          while (rdp_loop(deactivated, ext_disc_reason))
1264                    ;
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
   
         return res;  
1265  }  }
1266    
1267  BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1268    BOOL
1269    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1270  {  {
1271          BOOL res = True;          uint8 type;
1272            BOOL disc = False;      /* True when a disconnect PDU was received */
1273          res = res ? lsb_io_uint16(s, &rso->length) : False;          BOOL cont = True;
1274          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          STREAM s;
         res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
1275    
1276          return res;          while (cont)
1277            {
1278                    s = rdp_recv(&type);
1279                    if (s == NULL)
1280                            return False;
1281                    switch (type)
1282                    {
1283                            case RDP_PDU_DEMAND_ACTIVE:
1284                                    process_demand_active(s);
1285                                    *deactivated = False;
1286                                    break;
1287                            case RDP_PDU_DEACTIVATE:
1288                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1289                                    *deactivated = True;
1290                                    break;
1291                            case RDP_PDU_DATA:
1292                                    disc = process_data_pdu(s, ext_disc_reason);
1293                                    break;
1294                            case 0:
1295                                    break;
1296                            default:
1297                                    unimpl("PDU %d\n", type);
1298                    }
1299                    if (disc)
1300                            return False;
1301                    cont = g_next_packet < s->end;
1302            }
1303            return True;
1304  }  }
1305    
1306  BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)  /* Establish a connection up to the RDP layer */
1307    BOOL
1308    rdp_connect(char *server, uint32 flags, char *domain, char *password,
1309                char *command, char *directory)
1310  {  {
1311          BOOL res = True;          if (!sec_connect(server, g_username))
1312                    return False;
         res = res ? prs_io_uint8 (s, &rdh->cache_id  ) : False;  
         res = res ? prs_io_uint8 (s, &rdh->pad1      ) : False;  
         res = res ? prs_io_uint8 (s, &rdh->width     ) : False;  
         res = res ? prs_io_uint8 (s, &rdh->height    ) : False;  
         res = res ? prs_io_uint8 (s, &rdh->bpp       ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->bufsize   ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->cache_idx ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->pad2      ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->size      ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->row_size  ) : False;  
         res = res ? lsb_io_uint16(s, &rdh->final_size) : False;  
1313    
1314          return res;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1315            return True;
1316  }  }
1317    
1318  BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr)  /* Disconnect from the RDP layer */
1319    void
1320    rdp_disconnect(void)
1321  {  {
1322          BOOL res = True;          sec_disconnect();
   
         res = res ? lsb_io_uint16(s, &ptr->message) : False;  
         res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;  
         res = res ? lsb_io_uint16(s, &ptr->x      ) : False;  
         res = res ? lsb_io_uint16(s, &ptr->y      ) : False;  
   
         return res;  
1323  }  }

Legend:
Removed from v.7  
changed lines
  Added in v.865

  ViewVC Help
Powered by ViewVC 1.1.26