/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.6  
changed lines
  Added in v.831

  ViewVC Help
Powered by ViewVC 1.1.26