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

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

  ViewVC Help
Powered by ViewVC 1.1.26