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

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

  ViewVC Help
Powered by ViewVC 1.1.26