/[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 905 by jdmeijer, Fri May 20 22:09:32 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);  
126    
127          if (present & 1)          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
128                  rdp_io_coord(&conn->in, &os->opaque_rect.x, delta);          s_push_layer(s, rdp_hdr, 18);
129    
130          if (present & 2)          return s;
                 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);  
   
         if (present & 16)  
                 prs_io_uint8(&conn->in, &os->opaque_rect.colour);  
   
         fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y);  
         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;  
   
         lsb_io_uint16(&conn->in, &num_orders);  
165    
166          conn->in.offset += 2;          memset(pout, 0, len + 4);
         //      p = &conn->in.data[conn->in.offset];  
167    
168          //      fprintf(stderr, "%02X %02X %02X %02X\n", p[0], p[1], p[2], p[3]);          if (g_iconv_works)
   
         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"));
 {  
         mcs_init_data(conn);  
         PUSH_LAYER(conn->out, rdp_offset, 18);  
 }  
416    
417  /* Transmit RDP transport data packet */                  out_uint32_le(s, 0x30000);
418  void rdp_send_data(HCONN conn, uint16 data_pdu_type)                  out_uint32_le(s, 0x050000);
419  {                  out_uint32_le(s, 2);
420          RDP_HEADER hdr;                  out_uint32(s, 0);
421          RDP_DATA_HEADER datahdr;                  out_uint32_le(s, 0xffffffc4);
422          int length = conn->out.end - conn->out.offset;                  out_uint32_le(s, 0xfffffffe);
423                    out_uint32_le(s, g_rdp5_performanceflags);
424                    out_uint32(s, 0);
425    
426          POP_LAYER(conn->out, rdp_offset);  
427          length = conn->out.end - conn->out.offset;          }
428          rdp_make_header(&hdr, length, RDP_PDU_DATA, conn->mcs_userid);          s_mark_end(s);
429          rdp_io_header(&conn->out, &hdr);          sec_send(s, sec_flags);
         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          rdp_init_data(conn);          s = rdp_init_data(16);
         rdp_make_input_pdu(&input);  
         rdp_io_input_pdu(&conn->out, &input);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_INPUT);  
 }  
470    
471  BOOL rdp_recv_pdu(HCONN conn, uint8 *type)          out_uint16_le(s, 1);    /* number of events */
472  {          out_uint16(s, 0);       /* pad */
         RDP_HEADER hdr;  
473    
474          conn->in.offset = conn->in.rdp_offset;          out_uint32_le(s, time);
475            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          if (conn->in.offset >= conn->in.end)          s_mark_end(s);
481          {          rdp_send_data(s, RDP_DATA_PDU_INPUT);
482                  if (!mcs_recv(conn, False))  }
                         return False;  
         }  
483    
484          if (!rdp_io_header(&conn->in, &hdr))  /* Send a client window information PDU */
485                  return False;  void
486    rdp_send_client_window_status(int status)
487    {
488            STREAM s;
489    
490          conn->in.rdp_offset += hdr.length;          s = rdp_init_data(12);
         *type = hdr.pdu_type & 0xf;  
491    
492  #if DEBUG          out_uint32_le(s, status);
         fprintf(stderr, "RDP packet (type %x):\n", *type);  
         dump_data(conn->in.data+conn->in.offset, conn->in.rdp_offset-conn->in.offset);  
 #endif  
493    
494          return True;          switch (status)
495  }          {
496                    case 0: /* shut the server up */
497                            break;
498    
499  /* Disconnect from the RDP layer */                  case 1: /* receive data again */
500  void rdp_disconnect(HCONN conn)                          out_uint32_le(s, 0);    /* unknown */
501  {                          out_uint16_le(s, g_width);
502          mcs_disconnect(conn);                          out_uint16_le(s, g_height);
503  }                          break;
504            }
505    
506  void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,          s_mark_end(s);
507                       uint16 userid)          rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
 {  
         hdr->length = length;  
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
508  }  }
509    
510  void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,  /* Send persistent bitmap cache enumeration PDU's */
511                            uint16 length, uint16 data_pdu_type)  static void
512  {  rdp_enum_bmpcache2(void)
513          hdr->shareid = shareid;  {
514          hdr->pad = 0;          STREAM s;
515          hdr->streamid = 1;          HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
516          hdr->length = length - 14;          uint32 num_keys, offset, count, flags;
517          hdr->data_pdu_type = data_pdu_type;  
518          hdr->compress_type = 0;          offset = 0;
519          hdr->compress_len = 0;          num_keys = pstcache_enumerate(2, keylist);
520    
521            while (offset < num_keys)
522            {
523                    count = MIN(num_keys - offset, 169);
524    
525                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
526    
527                    flags = 0;
528                    if (offset == 0)
529                            flags |= PDU_FLAG_FIRST;
530                    if (num_keys - offset <= 169)
531                            flags |= PDU_FLAG_LAST;
532    
533                    /* header */
534                    out_uint32_le(s, 0);
535                    out_uint16_le(s, count);
536                    out_uint16_le(s, 0);
537                    out_uint16_le(s, 0);
538                    out_uint16_le(s, 0);
539                    out_uint16_le(s, 0);
540                    out_uint16_le(s, num_keys);
541                    out_uint32_le(s, 0);
542                    out_uint32_le(s, flags);
543    
544                    /* list */
545                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
546    
547                    s_mark_end(s);
548                    rdp_send_data(s, 0x2b);
549    
550                    offset += 169;
551            }
552    }
553    
554    /* Send an (empty) font information PDU */
555    static void
556    rdp_send_fonts(uint16 seq)
557    {
558            STREAM s;
559    
560            s = rdp_init_data(8);
561    
562            out_uint16(s, 0);       /* number of fonts */
563            out_uint16_le(s, 0);    /* pad? */
564            out_uint16_le(s, seq);  /* unknown */
565            out_uint16_le(s, 0x32); /* entry size */
566    
567            s_mark_end(s);
568            rdp_send_data(s, RDP_DATA_PDU_FONT2);
569    }
570    
571    /* Output general capability set */
572    static void
573    rdp_out_general_caps(STREAM s)
574    {
575            out_uint16_le(s, RDP_CAPSET_GENERAL);
576            out_uint16_le(s, RDP_CAPLEN_GENERAL);
577    
578            out_uint16_le(s, 1);    /* OS major type */
579            out_uint16_le(s, 3);    /* OS minor type */
580            out_uint16_le(s, 0x200);        /* Protocol version */
581            out_uint16(s, 0);       /* Pad */
582            out_uint16(s, 0);       /* Compression types */
583            out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
584            /* Pad, according to T.128. 0x40d seems to
585               trigger
586               the server to start sending RDP5 packets.
587               However, the value is 0x1d04 with W2KTSK and
588               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
589               for sending such information in a padding
590               field.. */
591            out_uint16(s, 0);       /* Update capability */
592            out_uint16(s, 0);       /* Remote unshare capability */
593            out_uint16(s, 0);       /* Compression level */
594            out_uint16(s, 0);       /* Pad */
595    }
596    
597    /* Output bitmap capability set */
598    static void
599    rdp_out_bitmap_caps(STREAM s)
600    {
601            out_uint16_le(s, RDP_CAPSET_BITMAP);
602            out_uint16_le(s, RDP_CAPLEN_BITMAP);
603    
604            out_uint16_le(s, g_server_bpp); /* Preferred BPP */
605            out_uint16_le(s, 1);    /* Receive 1 BPP */
606            out_uint16_le(s, 1);    /* Receive 4 BPP */
607            out_uint16_le(s, 1);    /* Receive 8 BPP */
608            out_uint16_le(s, 800);  /* Desktop width */
609            out_uint16_le(s, 600);  /* Desktop height */
610            out_uint16(s, 0);       /* Pad */
611            out_uint16(s, 1);       /* Allow resize */
612            out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
613            out_uint16(s, 0);       /* Unknown */
614            out_uint16_le(s, 1);    /* Unknown */
615            out_uint16(s, 0);       /* Pad */
616    }
617    
618    /* Output order capability set */
619    static void
620    rdp_out_order_caps(STREAM s)
621    {
622            uint8 order_caps[32];
623    
624            memset(order_caps, 0, 32);
625            order_caps[0] = 1;      /* dest blt */
626            order_caps[1] = 1;      /* pat blt */
627            order_caps[2] = 1;      /* screen blt */
628            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
629            order_caps[4] = 0;      /* triblt */
630            order_caps[8] = 1;      /* line */
631            order_caps[9] = 1;      /* line */
632            order_caps[10] = 1;     /* rect */
633            order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
634            order_caps[13] = 1;     /* memblt */
635            order_caps[14] = 1;     /* triblt */
636            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
637            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
638            order_caps[22] = 1;     /* polyline */
639            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
640            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
641            order_caps[27] = 1;     /* text2 */
642            out_uint16_le(s, RDP_CAPSET_ORDER);
643            out_uint16_le(s, RDP_CAPLEN_ORDER);
644    
645            out_uint8s(s, 20);      /* Terminal desc, pad */
646            out_uint16_le(s, 1);    /* Cache X granularity */
647            out_uint16_le(s, 20);   /* Cache Y granularity */
648            out_uint16(s, 0);       /* Pad */
649            out_uint16_le(s, 1);    /* Max order level */
650            out_uint16_le(s, 0x147);        /* Number of fonts */
651            out_uint16_le(s, 0x2a); /* Capability flags */
652            out_uint8p(s, order_caps, 32);  /* Orders supported */
653            out_uint16_le(s, 0x6a1);        /* Text capability flags */
654            out_uint8s(s, 6);       /* Pad */
655            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
656            out_uint32(s, 0);       /* Unknown */
657            out_uint32_le(s, 0x4e4);        /* Unknown */
658    }
659    
660    /* Output bitmap cache capability set */
661    static void
662    rdp_out_bmpcache_caps(STREAM s)
663    {
664            int Bpp;
665            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
666            out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
667    
668            Bpp = (g_server_bpp + 7) / 8;
669            out_uint8s(s, 24);      /* unused */
670            out_uint16_le(s, 0x258);        /* entries */
671            out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
672            out_uint16_le(s, 0x12c);        /* entries */
673            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
674            out_uint16_le(s, 0x106);        /* entries */
675            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
676    }
677    
678    /* Output bitmap cache v2 capability set */
679    static void
680    rdp_out_bmpcache2_caps(STREAM s)
681    {
682            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
683            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
684    
685            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
686    
687            out_uint16_be(s, 3);    /* number of caches in this set */
688    
689            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
690            out_uint32_le(s, BMPCACHE2_C0_CELLS);
691            out_uint32_le(s, BMPCACHE2_C1_CELLS);
692            if (pstcache_init(2))
693            {
694                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
695            }
696            else
697            {
698                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
699            }
700            out_uint8s(s, 20);      /* other bitmap caches not used */
701  }  }
702    
703  void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  /* Output control capability set */
704    static void
705    rdp_out_control_caps(STREAM s)
706  {  {
707          caps->os_major_type = 1;          out_uint16_le(s, RDP_CAPSET_CONTROL);
708          caps->os_minor_type = 3;          out_uint16_le(s, RDP_CAPLEN_CONTROL);
         caps->ver_protocol = 0x200;  
 }  
709    
710  void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps)          out_uint16(s, 0);       /* Control capabilities */
711  {          out_uint16(s, 0);       /* Remote detach */
712          caps->preferred_bpp = 8;          out_uint16_le(s, 2);    /* Control interest */
713          caps->receive1bpp = 1;          out_uint16_le(s, 2);    /* Detach interest */
         caps->receive4bpp = 1;  
         caps->receive8bpp = 1;  
         caps->width = 640;  
         caps->height = 480;  
         caps->compression = 1;  
         caps->unknown2 = 1;  
714  }  }
715    
716  void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  /* Output activation capability set */
717    static void
718    rdp_out_activate_caps(STREAM s)
719  {  {
720          caps->xgranularity = 1;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
721          caps->ygranularity = 20;          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
722    
723  //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;          out_uint16(s, 0);       /* Help key */
724            out_uint16(s, 0);       /* Help index key */
725          caps->support[0] = caps->support[1] = caps->support[2]          out_uint16(s, 0);       /* Extended help key */
726                  = caps->support[3] = caps->support[4] = caps->support[5]          out_uint16(s, 0);       /* Window activate */
                 = 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;  
727  }  }
728    
729  void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  /* Output pointer capability set */
730    static void
731    rdp_out_pointer_caps(STREAM s)
732  {  {
733          caps->caches[0].entries = 0x258;          out_uint16_le(s, RDP_CAPSET_POINTER);
734          caps->caches[0].max_cell_size = 0x100;          out_uint16_le(s, RDP_CAPLEN_POINTER);
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
 }  
735    
736  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)          out_uint16(s, 0);       /* Colour pointer */
737  {          out_uint16_le(s, 20);   /* Cache size */
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
738  }  }
739    
740  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  /* Output share capability set */
741    static void
742    rdp_out_share_caps(STREAM s)
743  {  {
744  }          out_uint16_le(s, RDP_CAPSET_SHARE);
745            out_uint16_le(s, RDP_CAPLEN_SHARE);
746    
747  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)          out_uint16(s, 0);       /* userid */
748  {          out_uint16(s, 0);       /* pad */
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
749  }  }
750    
751  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  /* Output colour cache capability set */
752    static void
753    rdp_out_colcache_caps(STREAM s)
754  {  {
755  }          out_uint16_le(s, RDP_CAPSET_COLCACHE);
756            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
757    
758  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)          out_uint16_le(s, 6);    /* cache size */
759  {          out_uint16(s, 0);       /* pad */
         caps->cache_size = 6;  
760  }  }
761    
762  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid)  static uint8 caps_0x0d[] = {
763  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
764          memset(pdu, 0, sizeof(*pdu));          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765          pdu->shareid = shareid;          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766          pdu->userid  = 1002;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767          pdu->source_len = sizeof(RDP_SOURCE);          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768          memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770            0x00, 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
774    };
775    
776          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
                 + 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;  
777    
778          rdp_make_general_caps (&pdu->general_caps );  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
         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);  
 }  
779    
780  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  static uint8 caps_0x10[] = {
781  {          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
782          pdu->action = action;          0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
783          pdu->userid = 0;          0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
784          pdu->controlid = 0;          0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
785  }          0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
786            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
787    };
788    
789  void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid)  /* Output unknown capability sets */
790    static void
791    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
792  {  {
793          pdu->type = 1;          out_uint16_le(s, id);
794          pdu->userid = userid;          out_uint16_le(s, length);
 }  
795    
796  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          out_uint8p(s, caps, length - 4);
 {  
         pdu->num_fonts = 0;  
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
797  }  }
798    
799  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu)  #define RDP5_FLAG 0x0030
800    /* Send a confirm active PDU */
801    static void
802    rdp_send_confirm_active(void)
803  {  {
804          uint32 now = time(NULL);          STREAM s;
805            uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
806            uint16 caplen =
807                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
808                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
809                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
810                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
811                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
812                    4 /* w2k fix, why? */ ;
813    
814          pdu->num_events = 3;          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
         pdu->pad = 0;  
815    
816          pdu->event[0].event_time = now;          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
817          pdu->event[0].message_type = RDP_INPUT_SYNCHRONIZE;          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
818          pdu->event[0].device_flags = 0;          out_uint16_le(s, (g_mcs_userid + 1001));
         pdu->event[0].mouse_x = 0;  
         pdu->event[0].mouse_y = 0;  
819    
820          pdu->event[1].event_time = now;          out_uint32_le(s, g_rdp_shareid);
821          pdu->event[1].message_type = RDP_INPUT_UNKNOWN;          out_uint16_le(s, 0x3ea);        /* userid */
822          pdu->event[1].device_flags = 0x8000;          out_uint16_le(s, sizeof(RDP_SOURCE));
823          pdu->event[1].mouse_x = 15;          out_uint16_le(s, caplen);
         pdu->event[1].mouse_y = 0;  
824    
825          pdu->event[2].event_time = now;          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
826          pdu->event[2].message_type = RDP_INPUT_MOUSE;          out_uint16_le(s, 0xd);  /* num_caps */
827          pdu->event[2].device_flags = MOUSE_FLAG_MOVE;          out_uint8s(s, 2);       /* pad */
         pdu->event[2].mouse_x = 425;  
         pdu->event[2].mouse_y = 493;  
 }  
828    
829  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)          rdp_out_general_caps(s);
830  {          rdp_out_bitmap_caps(s);
831          BOOL res = True;          rdp_out_order_caps(s);
832            g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
833            rdp_out_colcache_caps(s);
834            rdp_out_activate_caps(s);
835            rdp_out_control_caps(s);
836            rdp_out_pointer_caps(s);
837            rdp_out_share_caps(s);
838    
839          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
840          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
841          res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;          rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
842            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
843    
844          return res;          s_mark_end(s);
845            sec_send(s, sec_flags);
846  }  }
847    
848  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)  /* Process a general capability set */
849    static void
850    rdp_process_general_caps(STREAM s)
851  {  {
852          BOOL res = True;          uint16 pad2octetsB;     /* rdp5 flags? */
853    
854          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;          in_uint8s(s, 10);
855          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;          in_uint16_le(s, pad2octetsB);
         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;  
856    
857          return res;          if (!pad2octetsB)
858                    g_use_rdp5 = False;
859  }  }
860    
861  BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)  /* Process a bitmap capability set */
862    static void
863    rdp_process_bitmap_caps(STREAM s)
864  {  {
865          uint8 change;          uint16 width, height, bpp;
866          BOOL res;  
867            in_uint16_le(s, bpp);
868            in_uint8s(s, 6);
869    
870            in_uint16_le(s, width);
871            in_uint16_le(s, height);
872    
873            DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
874    
875          if (delta)          /*
876             * The server may limit bpp and change the size of the desktop (for
877             * example when shadowing another session).
878             */
879            if (g_server_bpp != bpp)
880          {          {
881                  res = prs_io_uint8(s, &change);                  warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
882                  *coord += change;                  g_server_bpp = bpp;
883          }          }
884          else          if (g_width != width || g_height != height)
885          {          {
886                  res = lsb_io_uint16(s, coord);                  warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
887                            width, height);
888                    g_width = width;
889                    g_height = height;
890                    ui_resize_window();
891          }          }
   
         return res;  
892  }  }
893    
894  BOOL rdp_io_colormap(STREAM s, COLORMAP *colors)  /* Process server capabilities */
895    void
896    rdp_process_server_caps(STREAM s, uint16 length)
897  {  {
898          int datasize;          int n;
899            uint8 *next, *start;
900          lsb_io_uint16(s, &colors->ncolors);          uint16 ncapsets, capset_type, capset_length;
         datasize = colors->ncolors * 3;  
901    
902          if (datasize > sizeof(colors->colors))          start = s->p;
                 return False;  
   
         memcpy(colors->colors, s->data + s->offset, datasize);  
         s->offset += datasize;  
         return True;  
 }  
903    
904  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)          in_uint16_le(s, ncapsets);
905  {          in_uint8s(s, 2);        /* pad */
         uint16 length = RDP_CAPLEN_GENERAL;  
         uint16 pkt_length = length;  
         BOOL res;  
906    
907          res = lsb_io_uint16(s, &pkt_length);          for (n = 0; n < ncapsets; n++)
         if (pkt_length != length)  
908          {          {
909                  fprintf(stderr, "Unrecognised capabilities size\n");                  if (s->p > start + length)
910                  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;  
911    
912          res = lsb_io_uint16(s, &pkt_length);                  in_uint16_le(s, capset_type);
913          if (pkt_length != length)                  in_uint16_le(s, capset_length);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
914    
915          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;  
916    
917          res = lsb_io_uint16(s, &pkt_length);                  switch (capset_type)
918          if (pkt_length != length)                  {
919          {                          case RDP_CAPSET_GENERAL:
920                  fprintf(stderr, "Unrecognised capabilities size\n");                                  rdp_process_general_caps(s);
921                  return False;                                  break;
         }  
922    
923          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;                          case RDP_CAPSET_BITMAP:
924          res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;                                  rdp_process_bitmap_caps(s);
925          res = res ? lsb_io_uint16(s, &caps->xgranularity     ) : False;                                  break;
926          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;  
927    
928          return res;                  s->p = next;
929            }
930  }  }
931    
932  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  /* Respond to a demand active PDU */
933    static void
934    process_demand_active(STREAM s)
935  {  {
936          if (!lsb_io_uint16(s, &info->entries      ))          uint8 type;
937                  return False;          uint16 len_src_descriptor, len_combined_caps;
   
         if (!lsb_io_uint16(s, &info->max_cell_size))  
                 return False;  
   
         return True;  
 }  
938    
939  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)          in_uint32_le(s, g_rdp_shareid);
940  {          in_uint16_le(s, len_src_descriptor);
941          uint16 length = RDP_CAPLEN_BMPCACHE;          in_uint16_le(s, len_combined_caps);
942          uint16 pkt_length = length;          in_uint8s(s, len_src_descriptor);
943          BOOL res;  
944          int i;          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
945            rdp_process_server_caps(s, len_combined_caps);
946    
947            rdp_send_confirm_active();
948            rdp_send_synchronise();
949            rdp_send_control(RDP_CTL_COOPERATE);
950            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
951            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
952            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
953            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
954            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
955    
956          res = lsb_io_uint16(s, &pkt_length);          if (g_use_rdp5)
         if (pkt_length != length)  
957          {          {
958                  fprintf(stderr, "Unrecognised capabilities size\n");                  rdp_enum_bmpcache2();
959                  return False;                  rdp_send_fonts(3);
960            }
961            else
962            {
963                    rdp_send_fonts(1);
964                    rdp_send_fonts(2);
965          }          }
966    
967          for (i = 0; i < 6; i++)          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
968                  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;  
969  }  }
970    
971  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  /* Process a colour pointer PDU */
972    void
973    process_colour_pointer_pdu(STREAM s)
974  {  {
975          uint16 length = RDP_CAPLEN_CONTROL;          uint16 x, y, width, height, cache_idx, masklen, datalen;
976          uint16 pkt_length = length;          uint8 *mask, *data;
977          BOOL res;          HCURSOR cursor;
978    
979          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, cache_idx);
980          if (pkt_length != length)          in_uint16_le(s, x);
981          {          in_uint16_le(s, y);
982                  fprintf(stderr, "Unrecognised capabilities size\n");          in_uint16_le(s, width);
983                  return False;          in_uint16_le(s, height);
984          }          in_uint16_le(s, masklen);
985            in_uint16_le(s, datalen);
986            in_uint8p(s, data, datalen);
987            in_uint8p(s, mask, masklen);
988            cursor = ui_create_cursor(x, y, width, height, mask, data);
989            ui_set_cursor(cursor);
990            cache_put_cursor(cache_idx, cursor);
991    }
992    
993          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;  /* Process a cached pointer PDU */
994          res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;  void
995          res = res ? lsb_io_uint16(s, &caps->control_interest) : False;  process_cached_pointer_pdu(STREAM s)
996          res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  {
997            uint16 cache_idx;
998    
999          return res;          in_uint16_le(s, cache_idx);
1000            ui_set_cursor(cache_get_cursor(cache_idx));
1001  }  }
1002    
1003  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  /* Process a system pointer PDU */
1004    void
1005    process_system_pointer_pdu(STREAM s)
1006  {  {
1007          uint16 length = RDP_CAPLEN_ACTIVATE;          uint16 system_pointer_type;
         uint16 pkt_length = length;  
         BOOL res;  
1008    
1009          res = lsb_io_uint16(s, &pkt_length);          in_uint16(s, system_pointer_type);
1010          if (pkt_length != length)          switch (system_pointer_type)
1011          {          {
1012                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_NULL_POINTER:
1013                  return False;                          ui_set_null_cursor();
1014          }                          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;  
1015    
1016          return res;                  default:
1017                            unimpl("System pointer message 0x%x\n", system_pointer_type);
1018            }
1019  }  }
1020    
1021  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  /* Process a pointer PDU */
1022    static void
1023    process_pointer_pdu(STREAM s)
1024  {  {
1025          uint16 length = RDP_CAPLEN_POINTER;          uint16 message_type;
1026          uint16 pkt_length = length;          uint16 x, y;
1027          BOOL res;  
1028            in_uint16_le(s, message_type);
1029            in_uint8s(s, 2);        /* pad */
1030    
1031          res = lsb_io_uint16(s, &pkt_length);          switch (message_type)
         if (pkt_length != length)  
1032          {          {
1033                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_POINTER_MOVE:
1034                  return False;                          in_uint16_le(s, x);
1035          }                          in_uint16_le(s, y);
1036                            if (s_check(s))
1037                                    ui_move_pointer(x, y);
1038                            break;
1039    
1040          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_POINTER_COLOR:
1041          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          process_colour_pointer_pdu(s);
1042                            break;
1043    
1044          return res;                  case RDP_POINTER_CACHED:
1045  }                          process_cached_pointer_pdu(s);
1046                            break;
1047    
1048  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                  case RDP_POINTER_SYSTEM:
1049  {                          process_system_pointer_pdu(s);
1050          uint16 length = RDP_CAPLEN_SHARE;                          break;
         uint16 pkt_length = length;  
         BOOL res;  
1051    
1052          res = lsb_io_uint16(s, &pkt_length);                  default:
1053          if (pkt_length != length)                          unimpl("Pointer message 0x%x\n", message_type);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
1054          }          }
   
         res = res ? lsb_io_uint16(s, &caps->userid) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad   ) : False;  
   
         return res;  
1055  }  }
1056    
1057  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  /* Process bitmap updates */
1058    void
1059    process_bitmap_updates(STREAM s)
1060  {  {
1061          uint16 length = RDP_CAPLEN_COLCACHE;          uint16 num_updates;
1062          uint16 pkt_length = length;          uint16 left, top, right, bottom, width, height;
1063          BOOL res;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1064            uint8 *data, *bmpdata;
1065            int i;
1066    
1067          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;  
         }  
1068    
1069          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          for (i = 0; i < num_updates; i++)
1070          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          {
1071                    in_uint16_le(s, left);
1072                    in_uint16_le(s, top);
1073                    in_uint16_le(s, right);
1074                    in_uint16_le(s, bottom);
1075                    in_uint16_le(s, width);
1076                    in_uint16_le(s, height);
1077                    in_uint16_le(s, bpp);
1078                    Bpp = (bpp + 7) / 8;
1079                    in_uint16_le(s, compress);
1080                    in_uint16_le(s, bufsize);
1081    
1082          return res;                  cx = right - left + 1;
1083  }                  cy = bottom - top + 1;
1084    
1085  uint8 canned_caps[] = {                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1086  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  
 };  
1087    
1088  BOOL rdp_io_unknown_caps(STREAM s, void *caps)                  if (!compress)
1089  {                  {
1090          uint16 length = 0x58;                          int y;
1091          uint16 pkt_length = length;                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1092          BOOL res;                          for (y = 0; y < height; y++)
1093                            {
1094                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1095                                              width * Bpp);
1096                            }
1097                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1098                            xfree(bmpdata);
1099                            continue;
1100                    }
1101    
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
1102    
1103          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;                  if (compress & 0x400)
1104                    {
1105                            size = bufsize;
1106                    }
1107                    else
1108                    {
1109                            in_uint8s(s, 2);        /* pad */
1110                            in_uint16_le(s, size);
1111                            in_uint8s(s, 4);        /* line_size, final_size */
1112                    }
1113                    in_uint8p(s, data, size);
1114                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1115                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1116                    {
1117                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1118                    }
1119                    else
1120                    {
1121                            DEBUG_RDP5(("Failed to decompress data\n"));
1122                    }
1123    
1124          return res;                  xfree(bmpdata);
1125            }
1126  }  }
1127    
1128  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  /* Process a palette update */
1129    void
1130    process_palette(STREAM s)
1131  {  {
1132          uint16 capset;          COLOURENTRY *entry;
1133          uint16 length;          COLOURMAP map;
1134          BOOL res;          HCOLOURMAP hmap;
1135          int i;          int i;
1136    
1137          res = lsb_io_uint32(s, &pdu->shareid);          in_uint8s(s, 2);        /* pad */
1138            in_uint16_le(s, map.ncolours);
1139            in_uint8s(s, 2);        /* pad */
1140    
1141          if (pdutype == RDP_PDU_CONFIRM_ACTIVE)          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
1142    
1143          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;  
1144    
1145          if (pdu->source_len > 48)          for (i = 0; i < map.ncolours; i++)
1146          {          {
1147                  fprintf(stderr, "RDP source descriptor too long\n");                  entry = &map.colours[i];
1148                  return False;                  in_uint8(s, entry->red);
1149                    in_uint8(s, entry->green);
1150                    in_uint8(s, entry->blue);
1151          }          }
1152    
1153          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          hmap = ui_create_colourmap(&map);
1154          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;  
1155    
1156                          if (!lsb_io_uint16(s, &capset))          xfree(map.colours);
1157                                  return False;  }
1158    
1159                          switch (capset)  /* Process an update PDU */
1160                          {  static void
1161                          case RDP_CAPSET_GENERAL:  process_update_pdu(STREAM s)
1162                                  res = rdp_io_general_caps (s, &pdu->general_caps );  {
1163                                  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);  
1164    
1165                                  if (!lsb_io_uint16(s, &length))          in_uint16_le(s, update_type);
                                         return False;  
1166    
1167                                  s->offset += (length - 4);          ui_begin_update();
1168                          }          switch (update_type)
1169                  }          {
1170          }                  case RDP_UPDATE_ORDERS:
1171                            in_uint8s(s, 2);        /* pad */
1172                            in_uint16_le(s, count);
1173                            in_uint8s(s, 2);        /* pad */
1174                            process_orders(s, count);
1175                            break;
1176    
1177          return res;                  case RDP_UPDATE_BITMAP:
1178  }                          process_bitmap_updates(s);
1179                            break;
1180    
1181  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)                  case RDP_UPDATE_PALETTE:
1182  {                          process_palette(s);
1183          BOOL res = True;                          break;
1184    
1185          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;                  case RDP_UPDATE_SYNCHRONIZE:
1186          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;                          break;
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
1187    
1188          return res;                  default:
1189                            unimpl("update %d\n", update_type);
1190            }
1191            ui_end_update();
1192  }  }
1193    
1194  BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu)  /* Process a disconnect PDU */
1195    void
1196    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1197  {  {
1198          BOOL res = True;          in_uint32_le(s, *ext_disc_reason);
   
         res = res ? lsb_io_uint16(s, &pdu->type  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid) : False;  
1199    
1200          return res;          DEBUG(("Received disconnect PDU\n"));
1201  }  }
1202    
1203  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  /* Process data PDU */
1204    static BOOL
1205    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1206  {  {
1207          BOOL res = True;          uint8 data_pdu_type;
1208            uint8 ctype;
1209            uint16 clen;
1210            uint32 len;
1211    
1212          res = res ? lsb_io_uint32(s, &evt->event_time)   : False;          uint32 roff, rlen;
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
1213    
1214          if (!res)          struct stream *ns = &(g_mppc_dict.ns);
1215                  return False;  
1216            in_uint8s(s, 6);        /* shareid, pad, streamid */
1217            in_uint16(s, len);
1218            in_uint8(s, data_pdu_type);
1219            in_uint8(s, ctype);
1220            in_uint16(s, clen);
1221            clen -= 18;
1222    
1223          switch (evt->message_type)          if (ctype & RDP_MPPC_COMPRESSED)
1224          {          {
1225          case RDP_INPUT_CODEPOINT:                  if (len > RDP_MPPC_DICT_SIZE)
1226          case RDP_INPUT_VIRTKEY:                          error("error decompressed packet size exceeds max\n");
1227                  res = res ? lsb_io_uint16(s, &evt->device_flags) : False;                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1228                  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;  
         }  
1229    
1230          return res;                  /* len -= 18; */
 }  
1231    
1232  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)                  /* allocate memory and copy the uncompressed data into the temporary stream */
1233  {                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
         BOOL res = True;  
         int i;  
1234    
1235          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;  
1236    
1237          if (pdu->num_events > RDP_MAX_EVENTS)                  ns->size = rlen;
1238          {                  ns->end = (ns->data + ns->size);
1239                  fprintf(stderr, "Too many events in one PDU\n");                  ns->p = ns->data;
1240                  return False;                  ns->rdp_hdr = ns->p;
         }  
1241    
1242          for (i = 0; i < pdu->num_events; i++)                  s = ns;
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
1243          }          }
1244    
1245          return res;          switch (data_pdu_type)
1246  }          {
1247                    case RDP_DATA_PDU_UPDATE:
1248                            process_update_pdu(s);
1249                            break;
1250    
1251  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)                  case RDP_DATA_PDU_CONTROL:
1252  {                          DEBUG(("Received Control PDU\n"));
1253          BOOL res = True;                          break;
1254    
1255          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;                  case RDP_DATA_PDU_SYNCHRONISE:
1256          res = res ? lsb_io_uint16(s, &font->flags    ) : False;                          DEBUG(("Received Sync PDU\n"));
1257          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;  
1258    
1259          return res;                  case RDP_DATA_PDU_POINTER:
1260  }                          process_pointer_pdu(s);
1261                            break;
1262    
1263  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)                  case RDP_DATA_PDU_BELL:
1264  {                          ui_bell();
1265          BOOL res = True;                          break;
         int i;  
1266    
1267          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;                  case RDP_DATA_PDU_LOGON:
1268          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;                          DEBUG(("Received Logon PDU\n"));
1269          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;                          /* User logged on */
1270          res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;                          break;
1271    
1272          if (pdu->num_fonts > RDP_MAX_FONTS)                  case RDP_DATA_PDU_DISCONNECT:
1273          {                          process_disconnect_pdu(s, ext_disc_reason);
1274                  fprintf(stderr, "Too many fonts in one PDU\n");                          return True;
                 return False;  
         }  
1275    
1276          for (i = 0; i < pdu->num_fonts; i++)                  default:
1277          {                          unimpl("data PDU %d\n", data_pdu_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
1278          }          }
1279            return False;
         return res;  
1280  }  }
1281    
1282  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  /* Process incoming packets */
1283    /* nevers gets out of here till app is done */
1284    void
1285    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1286  {  {
1287          BOOL res = True;          while (rdp_loop(deactivated, ext_disc_reason))
1288                    ;
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
   
         return res;  
1289  }  }
1290    
1291  BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1292    BOOL
1293    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1294  {  {
1295          BOOL res = True;          uint8 type;
1296            BOOL disc = False;      /* True when a disconnect PDU was received */
1297          res = res ? lsb_io_uint16(s, &rso->length) : False;          BOOL cont = True;
1298          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          STREAM s;
         res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
1299    
1300          return res;          while (cont)
1301            {
1302                    s = rdp_recv(&type);
1303                    if (s == NULL)
1304                            return False;
1305                    switch (type)
1306                    {
1307                            case RDP_PDU_DEMAND_ACTIVE:
1308                                    process_demand_active(s);
1309                                    *deactivated = False;
1310                                    break;
1311                            case RDP_PDU_DEACTIVATE:
1312                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1313                                    *deactivated = True;
1314                                    break;
1315                            case RDP_PDU_DATA:
1316                                    disc = process_data_pdu(s, ext_disc_reason);
1317                                    break;
1318                            case 0:
1319                                    break;
1320                            default:
1321                                    unimpl("PDU %d\n", type);
1322                    }
1323                    if (disc)
1324                            return False;
1325                    cont = g_next_packet < s->end;
1326            }
1327            return True;
1328  }  }
1329    
1330  BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)  /* Establish a connection up to the RDP layer */
1331    BOOL
1332    rdp_connect(char *server, uint32 flags, char *domain, char *password,
1333                char *command, char *directory)
1334  {  {
1335          BOOL res = True;          if (!sec_connect(server, g_username))
1336                    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;  
1337    
1338          return res;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1339            return True;
1340  }  }
1341    
1342  BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr)  /* Disconnect from the RDP layer */
1343    void
1344    rdp_disconnect(void)
1345  {  {
1346          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;  
1347  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26