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

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

  ViewVC Help
Powered by ViewVC 1.1.26