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

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

  ViewVC Help
Powered by ViewVC 1.1.26