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

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

  ViewVC Help
Powered by ViewVC 1.1.26