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

Legend:
Removed from v.4  
changed lines
  Added in v.725

  ViewVC Help
Powered by ViewVC 1.1.26