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

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

  ViewVC Help
Powered by ViewVC 1.1.26