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

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

  ViewVC Help
Powered by ViewVC 1.1.26