/[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 6 by matty, Wed Jul 5 07:44:21 2000 UTC revision 828 by stargo, Sun Mar 6 21:11:18 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            uint8 idlist[BMPCACHE2_NUM_PSTCELLS * sizeof(BITMAP_ID)];
390            uint32 nids, offset, count, flags;
391    
392          rdp_init_data(conn);          offset = 0;
393          rdp_make_synchronize_pdu(&sync, 1002);          nids = pstcache_enumerate(2, idlist);
         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 < nids)
396  {          {
397          RDP_CONTROL_PDU control;                  count = MIN(nids - offset, 169);
398    
399          rdp_init_data(conn);                  s = rdp_init_data(24 + count * sizeof(BITMAP_ID));
         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 (nids - 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, nids);
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, idlist + offset * sizeof(BITMAP_ID), count * sizeof(BITMAP_ID));
         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;  
499            memset(order_caps, 0, 32);
500            order_caps[0] = 1;      /* dest blt */
501            order_caps[1] = 1;      /* pat blt */
502            order_caps[2] = 1;      /* screen blt */
503            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
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[22] = 1;     /* polyline */
511            order_caps[27] = 1;     /* text2 */
512            out_uint16_le(s, RDP_CAPSET_ORDER);
513            out_uint16_le(s, RDP_CAPLEN_ORDER);
514    
515            out_uint8s(s, 20);      /* Terminal desc, pad */
516            out_uint16_le(s, 1);    /* Cache X granularity */
517            out_uint16_le(s, 20);   /* Cache Y granularity */
518            out_uint16(s, 0);       /* Pad */
519            out_uint16_le(s, 1);    /* Max order level */
520            out_uint16_le(s, 0x147);        /* Number of fonts */
521            out_uint16_le(s, 0x2a); /* Capability flags */
522            out_uint8p(s, order_caps, 32);  /* Orders supported */
523            out_uint16_le(s, 0x6a1);        /* Text capability flags */
524            out_uint8s(s, 6);       /* Pad */
525            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
526            out_uint32(s, 0);       /* Unknown */
527            out_uint32_le(s, 0x4e4);        /* Unknown */
528  }  }
529    
530  void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps)  /* Output bitmap cache capability set */
531    static void
532    rdp_out_bmpcache_caps(STREAM s)
533  {  {
534          caps->preferred_bpp = 8;          int Bpp;
535          caps->receive1bpp = 1;          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
536          caps->receive4bpp = 1;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
537          caps->receive8bpp = 1;  
538          caps->width = 640;          Bpp = (g_server_bpp + 7) / 8;
539          caps->height = 480;          out_uint8s(s, 24);      /* unused */
540          caps->compression = 1;          out_uint16_le(s, 0x258);        /* entries */
541          caps->unknown2 = 1;          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
542            out_uint16_le(s, 0x12c);        /* entries */
543            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
544            out_uint16_le(s, 0x106);        /* entries */
545            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
546  }  }
547    
548  void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  /* Output bitmap cache v2 capability set */
549    static void
550    rdp_out_bmpcache2_caps(STREAM s)
551  {  {
552          caps->xgranularity = 1;          out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
553          caps->ygranularity = 20;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
554    
555  //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;          out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
556    
557          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;  
 }  
558    
559  void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)          out_uint32_le(s, BMPCACHE2_C0_CELLS);
560  {          out_uint32_le(s, BMPCACHE2_C1_CELLS);
561          caps->caches[0].entries = 0x258;          if (pstcache_init(2))
562          caps->caches[0].max_cell_size = 0x100;          {
563          caps->caches[1].entries = 0x12c;                  out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
564          caps->caches[1].max_cell_size = 0x400;          }
565          caps->caches[2].entries = 0x106;          else
566          caps->caches[2].max_cell_size = 0x1000;          {
567                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
568            }
569            out_uint8s(s, 20);      /* other bitmap caches not used */
570  }  }
571    
572  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)  /* Output control capability set */
573    static void
574    rdp_out_control_caps(STREAM s)
575  {  {
576          caps->control_interest = 2;          out_uint16_le(s, RDP_CAPSET_CONTROL);
577          caps->detach_interest = 2;          out_uint16_le(s, RDP_CAPLEN_CONTROL);
578    
579            out_uint16(s, 0);       /* Control capabilities */
580            out_uint16(s, 0);       /* Remote detach */
581            out_uint16_le(s, 2);    /* Control interest */
582            out_uint16_le(s, 2);    /* Detach interest */
583  }  }
584    
585  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  /* Output activation capability set */
586    static void
587    rdp_out_activate_caps(STREAM s)
588  {  {
589            out_uint16_le(s, RDP_CAPSET_ACTIVATE);
590            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
591    
592            out_uint16(s, 0);       /* Help key */
593            out_uint16(s, 0);       /* Help index key */
594            out_uint16(s, 0);       /* Extended help key */
595            out_uint16(s, 0);       /* Window activate */
596  }  }
597    
598  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)  /* Output pointer capability set */
599    static void
600    rdp_out_pointer_caps(STREAM s)
601  {  {
602          caps->colour_pointer = 0;          out_uint16_le(s, RDP_CAPSET_POINTER);
603          caps->cache_size = 20;          out_uint16_le(s, RDP_CAPLEN_POINTER);
604    
605            out_uint16(s, 0);       /* Colour pointer */
606            out_uint16_le(s, 20);   /* Cache size */
607  }  }
608    
609  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  /* Output share capability set */
610    static void
611    rdp_out_share_caps(STREAM s)
612  {  {
613            out_uint16_le(s, RDP_CAPSET_SHARE);
614            out_uint16_le(s, RDP_CAPLEN_SHARE);
615    
616            out_uint16(s, 0);       /* userid */
617            out_uint16(s, 0);       /* pad */
618  }  }
619    
620  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  /* Output colour cache capability set */
621    static void
622    rdp_out_colcache_caps(STREAM s)
623  {  {
624          caps->cache_size = 6;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
625            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
626    
627            out_uint16_le(s, 6);    /* cache size */
628            out_uint16(s, 0);       /* pad */
629  }  }
630    
631  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid)  static uint8 caps_0x0d[] = {
632  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
633          memset(pdu, 0, sizeof(*pdu));          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634          pdu->shareid = shareid;          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635          pdu->userid  = 1002;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636          pdu->source_len = sizeof(RDP_SOURCE);          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637          memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642            0x00, 0x00, 0x00, 0x00
643    };
644    
645          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;  
646    
647          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);  
 }  
648    
649  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  static uint8 caps_0x10[] = {
650  {          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
651          pdu->action = action;          0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
652          pdu->userid = 0;          0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
653          pdu->controlid = 0;          0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
654  }          0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
655            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
656    };
657    
658  void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid)  /* Output unknown capability sets */
659    static void
660    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
661  {  {
662          pdu->type = 1;          out_uint16_le(s, id);
663          pdu->userid = userid;          out_uint16_le(s, length);
 }  
664    
665  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;  
666  }  }
667    
668  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu)  #define RDP5_FLAG 0x0030
669    /* Send a confirm active PDU */
670    static void
671    rdp_send_confirm_active(void)
672  {  {
673          uint32 now = time(NULL);          STREAM s;
674            uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
675            uint16 caplen =
676                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
677                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
678                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
679                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
680                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
681                    4 /* w2k fix, why? */ ;
682    
683          pdu->num_events = 3;          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
         pdu->pad = 0;  
684    
685          pdu->event[0].event_time = now;          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
686          pdu->event[0].message_type = RDP_INPUT_SYNCHRONIZE;          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
687          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;  
688    
689          pdu->event[1].event_time = now;          out_uint32_le(s, g_rdp_shareid);
690          pdu->event[1].message_type = RDP_INPUT_UNKNOWN;          out_uint16_le(s, 0x3ea);        /* userid */
691          pdu->event[1].device_flags = 0x8000;          out_uint16_le(s, sizeof(RDP_SOURCE));
692          pdu->event[1].mouse_x = 15;          out_uint16_le(s, caplen);
         pdu->event[1].mouse_y = 0;  
693    
694          pdu->event[2].event_time = now;          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
695          pdu->event[2].message_type = RDP_INPUT_MOUSE;          out_uint16_le(s, 0xd);  /* num_caps */
696          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;  
 }  
697    
698  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)          rdp_out_general_caps(s);
699  {          rdp_out_bitmap_caps(s);
700          BOOL res = True;          rdp_out_order_caps(s);
701            g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
702            rdp_out_colcache_caps(s);
703            rdp_out_activate_caps(s);
704            rdp_out_control_caps(s);
705            rdp_out_pointer_caps(s);
706            rdp_out_share_caps(s);
707    
708          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
709          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
710          res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;          rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
711            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
712    
713          return res;          s_mark_end(s);
714            sec_send(s, sec_flags);
715  }  }
716    
717  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)  /* Process a general capability set */
718    static void
719    rdp_process_general_caps(STREAM s)
720  {  {
721          BOOL res = True;          uint16 pad2octetsB;     /* rdp5 flags? */
722    
723          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;          in_uint8s(s, 10);
724          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;  
725    
726          return res;          if (!pad2octetsB)
727                    g_use_rdp5 = False;
728  }  }
729    
730  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  /* Process a bitmap capability set */
731    static void
732    rdp_process_bitmap_caps(STREAM s)
733  {  {
734          uint16 length = RDP_CAPLEN_GENERAL;          uint16 width, height, bpp;
         uint16 pkt_length = length;  
         BOOL res;  
735    
736          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, bpp);
737          if (pkt_length != length)          in_uint8s(s, 6);
738          {  
739                  fprintf(stderr, "Unrecognised capabilities size\n");          in_uint16_le(s, width);
740                  return False;          in_uint16_le(s, height);
         }  
741    
742          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;  
743    
744          res = lsb_io_uint16(s, &pkt_length);          /*
745          if (pkt_length != length)           * The server may limit bpp and change the size of the desktop (for
746             * example when shadowing another session).
747             */
748            if (g_server_bpp != bpp)
749          {          {
750                  fprintf(stderr, "Unrecognised capabilities size\n");                  warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
751                  return False;                  g_server_bpp = bpp;
752          }          }
753            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)  
754          {          {
755                  fprintf(stderr, "Unrecognised capabilities size\n");                  warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
756                  return False;                          width, height);
757                    g_width = width;
758                    g_height = height;
759                    ui_resize_window();
760          }          }
   
         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;  
761  }  }
762    
763  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  /* Process server capabilities */
764    void
765    rdp_process_server_caps(STREAM s, uint16 length)
766  {  {
767          if (!lsb_io_uint16(s, &info->entries      ))          int n;
768                  return False;          uint8 *next, *start;
769            uint16 ncapsets, capset_type, capset_length;
770    
771          if (!lsb_io_uint16(s, &info->max_cell_size))          start = s->p;
                 return False;  
772    
773          return True;          in_uint16_le(s, ncapsets);
774  }          in_uint8s(s, 2);        /* pad */
775    
776  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)  
777          {          {
778                  fprintf(stderr, "Unrecognised capabilities size\n");                  if (s->p > start + length)
779                  return False;                          return;
         }  
780    
781          for (i = 0; i < 6; i++)                  in_uint16_le(s, capset_type);
782                  res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;                  in_uint16_le(s, capset_length);
783    
784          for (i = 0; i < 3; i++)                  next = s->p + capset_length - 4;
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
785    
786          return res;                  switch (capset_type)
787                    {
788                            case RDP_CAPSET_GENERAL:
789                                    rdp_process_general_caps(s);
790                                    break;
791    
792                            case RDP_CAPSET_BITMAP:
793                                    rdp_process_bitmap_caps(s);
794                                    break;
795                    }
796    
797                    s->p = next;
798            }
799  }  }
800    
801  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  /* Respond to a demand active PDU */
802    static void
803    process_demand_active(STREAM s)
804  {  {
805          uint16 length = RDP_CAPLEN_CONTROL;          uint8 type;
806          uint16 pkt_length = length;          uint16 len_src_descriptor, len_combined_caps;
         BOOL res;  
807    
808          res = lsb_io_uint16(s, &pkt_length);          in_uint32_le(s, g_rdp_shareid);
809          if (pkt_length != length)          in_uint16_le(s, len_src_descriptor);
810            in_uint16_le(s, len_combined_caps);
811            in_uint8s(s, len_src_descriptor);
812    
813            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
814            rdp_process_server_caps(s, len_combined_caps);
815    
816            rdp_send_confirm_active();
817            rdp_send_synchronise();
818            rdp_send_control(RDP_CTL_COOPERATE);
819            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
820            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
821            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
822            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
823            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
824    
825            if (g_use_rdp5)
826          {          {
827                  fprintf(stderr, "Unrecognised capabilities size\n");                  rdp_enum_bmpcache2();
828                  return False;                  rdp_send_fonts(3);
829            }
830            else
831            {
832                    rdp_send_fonts(1);
833                    rdp_send_fonts(2);
834          }          }
835    
836          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
837          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;  
838  }  }
839    
840  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  /* Process a colour pointer PDU */
841    void
842    process_colour_pointer_pdu(STREAM s)
843  {  {
844          uint16 length = RDP_CAPLEN_ACTIVATE;          uint16 x, y, width, height, cache_idx, masklen, datalen;
845          uint16 pkt_length = length;          uint8 *mask, *data;
846          BOOL res;          HCURSOR cursor;
847    
848          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, cache_idx);
849          if (pkt_length != length)          in_uint16_le(s, x);
850          {          in_uint16_le(s, y);
851                  fprintf(stderr, "Unrecognised capabilities size\n");          in_uint16_le(s, width);
852                  return False;          in_uint16_le(s, height);
853          }          in_uint16_le(s, masklen);
854            in_uint16_le(s, datalen);
855            in_uint8p(s, data, datalen);
856            in_uint8p(s, mask, masklen);
857            cursor = ui_create_cursor(x, y, width, height, mask, data);
858            ui_set_cursor(cursor);
859            cache_put_cursor(cache_idx, cursor);
860    }
861    
862          res = res ? lsb_io_uint16(s, &caps->help_key         ) : False;  /* Process a cached pointer PDU */
863          res = res ? lsb_io_uint16(s, &caps->help_index_key   ) : False;  void
864          res = res ? lsb_io_uint16(s, &caps->help_extended_key) : False;  process_cached_pointer_pdu(STREAM s)
865          res = res ? lsb_io_uint16(s, &caps->window_activate  ) : False;  {
866            uint16 cache_idx;
867    
868          return res;          in_uint16_le(s, cache_idx);
869            ui_set_cursor(cache_get_cursor(cache_idx));
870  }  }
871    
872  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  /* Process a system pointer PDU */
873    void
874    process_system_pointer_pdu(STREAM s)
875  {  {
876          uint16 length = RDP_CAPLEN_POINTER;          uint16 system_pointer_type;
         uint16 pkt_length = length;  
         BOOL res;  
877    
878          res = lsb_io_uint16(s, &pkt_length);          in_uint16(s, system_pointer_type);
879          if (pkt_length != length)          switch (system_pointer_type)
880          {          {
881                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_NULL_POINTER:
882                  return False;                          ui_set_null_cursor();
883          }                          break;
   
         res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;  
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
884    
885          return res;                  default:
886                            unimpl("System pointer message 0x%x\n", system_pointer_type);
887            }
888  }  }
889    
890  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)  /* Process a pointer PDU */
891    static void
892    process_pointer_pdu(STREAM s)
893  {  {
894          uint16 length = RDP_CAPLEN_SHARE;          uint16 message_type;
895          uint16 pkt_length = length;          uint16 x, y;
896          BOOL res;  
897            in_uint16_le(s, message_type);
898            in_uint8s(s, 2);        /* pad */
899    
900          res = lsb_io_uint16(s, &pkt_length);          switch (message_type)
         if (pkt_length != length)  
901          {          {
902                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_POINTER_MOVE:
903                  return False;                          in_uint16_le(s, x);
904          }                          in_uint16_le(s, y);
905                            if (s_check(s))
906                                    ui_move_pointer(x, y);
907                            break;
908    
909          res = res ? lsb_io_uint16(s, &caps->userid) : False;                  case RDP_POINTER_COLOR:
910          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                          process_colour_pointer_pdu(s);
911                            break;
912    
913          return res;                  case RDP_POINTER_CACHED:
914                            process_cached_pointer_pdu(s);
915                            break;
916    
917                    case RDP_POINTER_SYSTEM:
918                            process_system_pointer_pdu(s);
919                            break;
920    
921                    default:
922                            unimpl("Pointer message 0x%x\n", message_type);
923            }
924  }  }
925    
926  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  /* Process bitmap updates */
927    void
928    process_bitmap_updates(STREAM s)
929  {  {
930          uint16 length = RDP_CAPLEN_COLCACHE;          uint16 num_updates;
931          uint16 pkt_length = length;          uint16 left, top, right, bottom, width, height;
932          BOOL res;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
933            uint8 *data, *bmpdata;
934            int i;
935    
936          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;  
         }  
937    
938          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          for (i = 0; i < num_updates; i++)
939          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          {
940                    in_uint16_le(s, left);
941                    in_uint16_le(s, top);
942                    in_uint16_le(s, right);
943                    in_uint16_le(s, bottom);
944                    in_uint16_le(s, width);
945                    in_uint16_le(s, height);
946                    in_uint16_le(s, bpp);
947                    Bpp = (bpp + 7) / 8;
948                    in_uint16_le(s, compress);
949                    in_uint16_le(s, bufsize);
950    
951          return res;                  cx = right - left + 1;
952  }                  cy = bottom - top + 1;
953    
954  uint8 canned_caps[] = {                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
955  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  
 };  
956    
957  BOOL rdp_io_unknown_caps(STREAM s, void *caps)                  if (!compress)
958  {                  {
959          uint16 length = 0x58;                          int y;
960          uint16 pkt_length = length;                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
961          BOOL res;                          for (y = 0; y < height; y++)
962                            {
963                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
964                                              width * Bpp);
965                            }
966                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
967                            xfree(bmpdata);
968                            continue;
969                    }
970    
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
971    
972          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;                  if (compress & 0x400)
973                    {
974                            size = bufsize;
975                    }
976                    else
977                    {
978                            in_uint8s(s, 2);        /* pad */
979                            in_uint16_le(s, size);
980                            in_uint8s(s, 4);        /* line_size, final_size */
981                    }
982                    in_uint8p(s, data, size);
983                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
984                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
985                    {
986                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
987                    }
988                    else
989                    {
990                            DEBUG_RDP5(("Failed to decompress data\n"));
991                    }
992    
993          return res;                  xfree(bmpdata);
994            }
995  }  }
996    
997  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  /* Process a palette update */
998    void
999    process_palette(STREAM s)
1000  {  {
1001          uint16 capset;          COLOURENTRY *entry;
1002          uint16 length;          COLOURMAP map;
1003          BOOL res;          HCOLOURMAP hmap;
1004          int i;          int i;
1005    
1006          res = lsb_io_uint32(s, &pdu->shareid);          in_uint8s(s, 2);        /* pad */
1007            in_uint16_le(s, map.ncolours);
1008            in_uint8s(s, 2);        /* pad */
1009    
1010          if (pdutype == RDP_PDU_CONFIRM_ACTIVE)          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
1011    
1012          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;  
1013    
1014          if (pdu->source_len > 48)          for (i = 0; i < map.ncolours; i++)
1015          {          {
1016                  fprintf(stderr, "RDP source descriptor too long\n");                  entry = &map.colours[i];
1017                  return False;                  in_uint8(s, entry->red);
1018                    in_uint8(s, entry->green);
1019                    in_uint8(s, entry->blue);
1020          }          }
1021    
1022          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          hmap = ui_create_colourmap(&map);
1023          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;  
1024    
1025                          if (!lsb_io_uint16(s, &capset))          xfree(map.colours);
1026                                  return False;  }
1027    
1028                          switch (capset)  /* Process an update PDU */
1029                          {  static void
1030                          case RDP_CAPSET_GENERAL:  process_update_pdu(STREAM s)
1031                                  res = rdp_io_general_caps (s, &pdu->general_caps );  {
1032                                  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);  
1033    
1034                                  if (!lsb_io_uint16(s, &length))          in_uint16_le(s, update_type);
                                         return False;  
1035    
1036                                  s->offset += (length - 4);          ui_begin_update();
1037                          }          switch (update_type)
1038                  }          {
1039          }                  case RDP_UPDATE_ORDERS:
1040                            in_uint8s(s, 2);        /* pad */
1041                            in_uint16_le(s, count);
1042                            in_uint8s(s, 2);        /* pad */
1043                            process_orders(s, count);
1044                            break;
1045    
1046          return res;                  case RDP_UPDATE_BITMAP:
1047  }                          process_bitmap_updates(s);
1048                            break;
1049    
1050  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)                  case RDP_UPDATE_PALETTE:
1051  {                          process_palette(s);
1052          BOOL res = True;                          break;
1053    
1054          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;                  case RDP_UPDATE_SYNCHRONIZE:
1055          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;                          break;
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
1056    
1057          return res;                  default:
1058                            unimpl("update %d\n", update_type);
1059            }
1060            ui_end_update();
1061  }  }
1062    
1063  BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu)  /* Process a disconnect PDU */
1064    void
1065    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1066  {  {
1067          BOOL res = True;          in_uint32_le(s, *ext_disc_reason);
1068    
1069          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;  
1070  }  }
1071    
1072  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  /* Process data PDU */
1073    static BOOL
1074    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1075  {  {
1076          BOOL res = True;          uint8 data_pdu_type;
1077            uint8 ctype;
1078            uint16 clen;
1079            uint32 len;
1080    
1081          res = res ? lsb_io_uint32(s, &evt->event_time)   : False;          uint32 roff, rlen;
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
1082    
1083          if (!res)          struct stream *ns = &(g_mppc_dict.ns);
                 return False;  
1084    
1085          switch (evt->message_type)          in_uint8s(s, 6);        /* shareid, pad, streamid */
1086            in_uint16(s, len);
1087            in_uint8(s, data_pdu_type);
1088            in_uint8(s, ctype);
1089            in_uint16(s, clen);
1090            clen -= 18;
1091    
1092            if (ctype & RDP_MPPC_COMPRESSED)
1093          {          {
1094          case RDP_INPUT_CODEPOINT:                  if (len > RDP_MPPC_DICT_SIZE)
1095          case RDP_INPUT_VIRTKEY:                          error("error decompressed packet size exceeds max\n");
1096                  res = res ? lsb_io_uint16(s, &evt->device_flags) : False;                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1097                  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;  
         }  
1098    
1099          return res;                  //len -= 18;
 }  
1100    
1101  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)                  /* allocate memory and copy the uncompressed data into the temporary stream */
1102  {                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
         BOOL res = True;  
         int i;  
1103    
1104          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;  
1105    
1106          if (pdu->num_events > RDP_MAX_EVENTS)                  ns->size = rlen;
1107          {                  ns->end = (ns->data + ns->size);
1108                  fprintf(stderr, "Too many events in one PDU\n");                  ns->p = ns->data;
1109                  return False;                  ns->rdp_hdr = ns->p;
         }  
1110    
1111          for (i = 0; i < pdu->num_events; i++)                  s = ns;
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
1112          }          }
1113    
1114          return res;          switch (data_pdu_type)
1115  }          {
1116                    case RDP_DATA_PDU_UPDATE:
1117                            process_update_pdu(s);
1118                            break;
1119    
1120  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)                  case RDP_DATA_PDU_CONTROL:
1121  {                          DEBUG(("Received Control PDU\n"));
1122          BOOL res = True;                          break;
1123    
1124          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;                  case RDP_DATA_PDU_SYNCHRONISE:
1125          res = res ? lsb_io_uint16(s, &font->flags    ) : False;                          DEBUG(("Received Sync PDU\n"));
1126          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;  
1127    
1128          return res;                  case RDP_DATA_PDU_POINTER:
1129  }                          process_pointer_pdu(s);
1130                            break;
1131    
1132  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)                  case RDP_DATA_PDU_BELL:
1133  {                          ui_bell();
1134          BOOL res = True;                          break;
         int i;  
1135    
1136          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;                  case RDP_DATA_PDU_LOGON:
1137          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;                          DEBUG(("Received Logon PDU\n"));
1138          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;                          /* User logged on */
1139          res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;                          break;
1140    
1141          if (pdu->num_fonts > RDP_MAX_FONTS)                  case RDP_DATA_PDU_DISCONNECT:
1142          {                          process_disconnect_pdu(s, ext_disc_reason);
1143                  fprintf(stderr, "Too many fonts in one PDU\n");                          return True;
                 return False;  
         }  
1144    
1145          for (i = 0; i < pdu->num_fonts; i++)                  default:
1146          {                          unimpl("data PDU %d\n", data_pdu_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
1147          }          }
1148            return False;
         return res;  
1149  }  }
1150    
1151  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  /* Process incoming packets */
1152    /* nevers gets out of here till app is done */
1153    void
1154    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1155  {  {
1156          BOOL res = True;          while (rdp_loop(deactivated, ext_disc_reason))
1157                    ;
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
   
         return res;  
1158  }  }
1159    
1160  BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1161    BOOL
1162    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1163  {  {
1164          BOOL res = True;          uint8 type;
1165            BOOL disc = False;      /* True when a disconnect PDU was received */
1166          res = res ? lsb_io_uint16(s, &rso->length) : False;          BOOL cont = True;
1167          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          STREAM s;
1168          res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
1169            while (cont)
1170          return res;          {
1171                    s = rdp_recv(&type);
1172                    if (s == NULL)
1173                            return False;
1174                    switch (type)
1175                    {
1176                            case RDP_PDU_DEMAND_ACTIVE:
1177                                    process_demand_active(s);
1178                                    *deactivated = False;
1179                                    break;
1180                            case RDP_PDU_DEACTIVATE:
1181                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1182                                    *deactivated = True;
1183                                    break;
1184                            case RDP_PDU_DATA:
1185                                    disc = process_data_pdu(s, ext_disc_reason);
1186                                    break;
1187                            case 0:
1188                                    break;
1189                            default:
1190                                    unimpl("PDU %d\n", type);
1191                    }
1192                    if (disc)
1193                            return False;
1194                    cont = g_next_packet < s->end;
1195            }
1196            return True;
1197  }  }
1198    
1199  BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)  /* Establish a connection up to the RDP layer */
1200    BOOL
1201    rdp_connect(char *server, uint32 flags, char *domain, char *password,
1202                char *command, char *directory)
1203  {  {
1204          BOOL res = True;          if (!sec_connect(server, g_username))
1205                    return False;
1206    
1207          res = res ? prs_io_uint8 (s, &rdh->cache_id  ) : False;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1208          res = res ? prs_io_uint8 (s, &rdh->pad1      ) : False;          return True;
1209          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;  
1210    
1211          return res;  /* Disconnect from the RDP layer */
1212    void
1213    rdp_disconnect(void)
1214    {
1215            sec_disconnect();
1216  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26