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

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

  ViewVC Help
Powered by ViewVC 1.1.26