/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdp.c

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

revision 6 by matty, Wed Jul 5 07:44:21 2000 UTC revision 381 by jsorg71, Fri May 30 21:59:56 2003 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
# Line 18  Line 18 
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 "rdesktop.h"
22    
23  /* Establish a connection up to the RDP layer */  extern uint16 g_mcs_userid;
24  HCONN rdp_connect(char *server)  extern char username[16];
25  {  extern BOOL bitmap_compression;
26          HCONN conn;  extern BOOL orders;
27          RDP_ACTIVE_PDU active;  extern BOOL encryption;
28          uint8 type;  extern BOOL desktop_save;
29    extern BOOL use_rdp5;
30          if ((conn = mcs_connect(server)) == NULL)  extern uint16 server_rdp_version;
31                  return NULL;  
32    uint8 *next_packet;
33          rdp_establish_key(conn);  uint32 rdp_shareid;
34          mcs_recv(conn, False); /* Server's licensing certificate */  
35          rdp_send_cert(conn);  #if WITH_DEBUG
36          mcs_recv(conn, False);  static uint32 packetno;
37    #endif
38    
39    /* Receive an RDP packet */
40    static STREAM
41    rdp_recv(uint8 * type)
42    {
43            static STREAM rdp_s;
44            uint16 length, pdu_type;
45    
46            if ((rdp_s == NULL) || (next_packet >= rdp_s->end))
47            {
48                    rdp_s = sec_recv();
49                    if (rdp_s == NULL)
50                            return NULL;
51    
52          if (!rdp_recv_pdu(conn, &type) || (type != RDP_PDU_DEMAND_ACTIVE))                  next_packet = rdp_s->p;
53            }
54            else
55          {          {
56                  fprintf(stderr, "RDP error, expected Demand Active\n");                  rdp_s->p = next_packet;
                 mcs_disconnect(conn);  
                 return NULL;  
57          }          }
58    
59          rdp_io_active_pdu(&conn->in, &active, RDP_PDU_DEMAND_ACTIVE);          in_uint16_le(rdp_s, length);
60          rdp_send_confirm_active(conn);          /* 32k packets are really 8, keepalive fix */
61          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  
   
         return conn;  
 }  
   
 void rdp_main_loop(HCONN conn)  
 {  
         RDP_DATA_HEADER hdr;  
         RDP_UPDATE_PDU update;  
         RDP_ORDER_STATE os;  
         uint8 type;  
   
         memset(&os, 0, sizeof(os));  
   
         while (rdp_recv_pdu(conn, &type))  
62          {          {
63                  if (type != RDP_PDU_DATA)                  next_packet += 8;
64                          continue;                  *type = 0;
65                    return rdp_s;
66            }
67            in_uint16_le(rdp_s, pdu_type);
68            in_uint8s(rdp_s, 2);    /* userid */
69            *type = pdu_type & 0xf;
70    
71                  rdp_io_data_header(&conn->in, &hdr);  #if WITH_DEBUG
72            DEBUG(("RDP packet #%d, (type %x)\n", ++packetno, *type));
73            //      hexdump(next_packet, length);
74    #endif /*  */
75    
76                  switch (hdr.data_pdu_type)          next_packet += length;
77                  {          return rdp_s;
                 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;  
                 }  
         }  
78  }  }
79    
80  void prs_io_coord(STREAM s, uint16 *coord, BOOL delta)  /* Initialise an RDP data packet */
81    static STREAM
82    rdp_init_data(int maxlen)
83  {  {
84          uint8 change;          STREAM s;
85    
86          if (delta)          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);
87          {          s_push_layer(s, rdp_hdr, 18);
88                  prs_io_uint8(s, &change);  
89                  *coord += change;          return s;
         }  
         else  
         {  
                 lsb_io_uint16(s, coord);  
         }  
90  }  }
91    
92  void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)  /* Send an RDP data packet */
93    static void
94    rdp_send_data(STREAM s, uint8 data_pdu_type)
95  {  {
96          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);  
97    
98          if (present & 4)          s_pop_layer(s, rdp_hdr);
99                  prs_io_coord(&conn->in, &os->opaque_rect.cx, delta);          length = s->end - s->p;
100    
101          if (present & 8)          out_uint16_le(s, length);
102                  prs_io_coord(&conn->in, &os->opaque_rect.cy, delta);          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
103            out_uint16_le(s, (g_mcs_userid + 1001));
104    
105          if (present & 16)          out_uint32_le(s, rdp_shareid);
106                  prs_io_uint8(&conn->in, &os->opaque_rect.colour);          out_uint8(s, 0);        /* pad */
107            out_uint8(s, 1);        /* streamid */
108            out_uint16_le(s, (length - 14));
109            out_uint8(s, data_pdu_type);
110            out_uint8(s, 0);        /* compress_type */
111            out_uint16(s, 0);       /* compress_len */
112    
113          fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y);          sec_send(s, encryption ? SEC_ENCRYPT : 0);
114  }  }
115    
116  void process_bmpcache(HCONN conn)  /* Output a string in Unicode */
117    void
118    rdp_out_unistr(STREAM s, char *string, int len)
119  {  {
120            int i = 0, j = 0;
121    
122          RDP_BITMAP_HEADER rbh;          len += 2;
         char *bmpdata;  
         HBITMAP bmp;  
         static int x = 0;  
   
         rdp_io_bitmap_header(&conn->in, &rbh);  
         fprintf(stderr, "Decompressing bitmap %d x %d, final size %d\n", rbh.width, rbh.height, rbh.final_size);  
   
         bmpdata = malloc(rbh.width * rbh.height);  
         bitmap_decompress(conn->in.data  
                           + conn->in.offset, rbh.size,  
                           bmpdata, rbh.width);  
         conn->in.offset += rbh.size;  
123    
124          bmp = ui_create_bitmap(conn->wnd, rbh.width, rbh.height, bmpdata);          while (i < len)
125          ui_paint_bitmap(conn->wnd, bmp, x, 0);          {
126          ui_destroy_bitmap(bmp);                  s->p[i++] = string[j++];
127                    s->p[i++] = 0;
128            }
129    
130          x += rbh.width;          s->p += len;
131  }  }
132    
133  void process_orders(HCONN conn, RDP_ORDER_STATE *os)  /* Parse a logon info packet */
134    static void
135    rdp_send_logon_info(uint32 flags, char *domain, char *user,
136                        char *password, char *program, char *directory)
137  {  {
138          uint16 num_orders;          int len_domain = 2 * strlen(domain);
139          int processed = 0;          int len_user = 2 * strlen(user);
140          BOOL res = True;          int len_password = 2 * strlen(password);
141          //      unsigned char *p;          int len_program = 2 * strlen(program);
142            int len_directory = 2 * strlen(directory);
143          lsb_io_uint16(&conn->in, &num_orders);          int len_ip = 2 * strlen("127.0.0.1");
144            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
145          conn->in.offset += 2;          int packetlen = 0;
146          //      p = &conn->in.data[conn->in.offset];          uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
147            STREAM s;
         //      fprintf(stderr, "%02X %02X %02X %02X\n", p[0], p[1], p[2], p[3]);  
148    
149          while ((processed < num_orders) && res)          if (!use_rdp5 || 1 == server_rdp_version)
150          {          {
151                  uint8 order_flags;                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
152    
153                  prs_io_uint8(&conn->in, &order_flags);                  s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
154                                 + len_program + len_directory + 10);
155    
156                  if (!(order_flags & RDP_ORDER_STANDARD))                  out_uint32(s, 0);
157                          return;                  out_uint32_le(s, flags);
158                    out_uint16_le(s, len_domain);
159                  if (order_flags & RDP_ORDER_SECONDARY)                  out_uint16_le(s, len_user);
160                    out_uint16_le(s, len_password);
161                    out_uint16_le(s, len_program);
162                    out_uint16_le(s, len_directory);
163                    rdp_out_unistr(s, domain, len_domain);
164                    rdp_out_unistr(s, user, len_user);
165                    rdp_out_unistr(s, password, len_password);
166                    rdp_out_unistr(s, program, len_program);
167                    rdp_out_unistr(s, directory, len_directory);
168            }
169            else
170            {
171                    flags |= RDP_LOGON_BLOB;
172                    DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
173                    packetlen = 4 + // Unknown uint32
174                            4 + // flags
175                            2 + // len_domain
176                            2 + // len_user
177                            (flags & RDP_LOGON_AUTO ? 2 : 0) + // len_password
178                            (flags & RDP_LOGON_BLOB ? 2 : 0) + // Length of BLOB
179                            2 + // len_program
180                            2 + // len_directory
181                            (0 < len_domain ? len_domain : 2) + // domain
182                            len_user +
183                            (flags & RDP_LOGON_AUTO ? len_password : 0) +
184                            0 + // We have no 512 byte BLOB. Perhaps we must?
185                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + // After the BLOB is a unknown int16. If there is a BLOB, that is.
186                            (0 < len_program ? len_program : 2) +
187                            (0 < len_directory ? len_directory : 2) +
188                            2 + // Unknown (2)
189                            2 + // Client ip length
190                            len_ip + // Client ip
191                            2 +  // DLL string length
192                            len_dll + // DLL string
193                            2 +  // Unknown
194                            2 +  // Unknown
195                            64 +  // Time zone #0
196                            2 +  // Unknown
197                            64 +  // Time zone #1
198                            32; // Unknown
199                            
200                    s = sec_init(sec_flags, packetlen);    
201                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
202    
203                    out_uint32(s, 0); // Unknown
204                    out_uint32_le(s, flags);
205                    out_uint16_le(s, len_domain);
206                    out_uint16_le(s, len_user);
207                    if (flags & RDP_LOGON_AUTO)
208                  {                  {
209                          RDP_SECONDARY_ORDER rso;                          out_uint16_le(s, len_password);
   
                         rdp_io_secondary_order(&conn->in, &rso);  
                         switch (rso.type)  
                         {  
                         case RDP_ORDER_BMPCACHE:  
                                 process_bmpcache(conn);  
                                 break;  
                         default:  
                                 fprintf(stderr, "Unknown secondary order %d\n",  
                                         rso.type);  
                                 return;  
                         }  
   
210    
211                  }                  }
212                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO)) {
213                  if (order_flags & RDP_ORDER_CHANGE)                          out_uint16_le(s, 0);
214                          prs_io_uint8(&conn->in, &os->order_type);                  }
215                    out_uint16_le(s, len_program);
216                  switch (os->order_type)                  out_uint16_le(s, len_directory);
217                    if (0 < len_domain)
218                            rdp_out_unistr(s, domain, len_domain);
219                    else
220                            out_uint16_le(s, 0);
221                    rdp_out_unistr(s, user, len_user);
222                    if (flags & RDP_LOGON_AUTO)
223                  {                  {
224                  case RDP_ORDER_OPAQUE_RECT:                          rdp_out_unistr(s, password, len_password);
                         process_opaque_rect(conn, os, order_flags & RDP_ORDER_DELTA);  
                         break;  
                 default:  
                         fprintf(stderr, "Unknown order %d\n", os->order_type);  
                         return;  
225                  }                  }
226                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))  {
227                  processed++;                          out_uint16_le(s, 0);
228          }                  }
229  }                  if (0 < len_program) {
230                            rdp_out_unistr(s, program, len_program);
231  /* Work this out later. This is useless anyway when encryption is off. */                          
232  uint8 precanned_key_packet[] = {                  } else {
233     0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00,                          out_uint16_le(s, 0);
234     0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6c,0x86,                  }
235     0xf7,0x99,0xef,0x60,0xc4,0x49,0x52,0xd0,0xd8,0xea,0xb5,0x4f,0x58,0x19,                  if (0 < len_directory) {
236     0x52,0x2a,0x93,0x83,0x57,0x4f,0x4e,0x04,0xde,0x96,0x51,0xab,0x13,0x20,                          rdp_out_unistr(s, directory, len_directory);
237     0xd8,0xe5,0x00,0x00,0x00,0x00,0x00,0x00                  } else {
238  };                          out_uint16_le(s, 0);
239                    }
240  /* Create an RC4 key and transfer it to the server */                  out_uint16_le(s, 2);
241  void rdp_establish_key(HCONN conn)                  out_uint16_le(s, len_ip+2); // Length of client ip
242  {                  rdp_out_unistr(s, "127.0.0.1", len_ip);
243          mcs_init_data(conn);                  out_uint16_le(s, len_dll+2);
244          memcpy(conn->out.data + conn->out.offset, precanned_key_packet,                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
245                 sizeof(precanned_key_packet));                  out_uint16_le(s, 0xffc4);
246          conn->out.offset += sizeof(precanned_key_packet);                  out_uint16_le(s, 0xffff);
247          MARK_END(conn->out);                  rdp_out_unistr(s, "GTB, normaltid",
248          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);                                 2*strlen("GTB, normaltid"));
249  }                  out_uint8s(s, 62-2*strlen("GTB, normaltid"));
250                                  
251  /* Horrible horrible certificate stuff. Work out later. */  
252  uint8 precanned_cert_packet[] = {                  out_uint32_le(s, 0x0a0000);
253  0x80,0x00,0x00,0x00,0x12,0x02,0xb4,0x04,0x01,0x00,0x00,                  out_uint32_le(s, 0x050000);
254  0x00,0x00,0x00,0x01,0x02,0x9d,0xa3,0x7a,0x93,0x34,0x7b,0x28,0x37,0x24,0xa0,0x1f,                  out_uint32_le(s, 3);
255  0x61,0x26,0xfd,0x96,0x3a,0x92,0x83,0xf3,0xe9,0x6a,0x2e,0x81,0x7c,0x2c,0xe4,0x72,//                  out_uint32_le(s, 0);
256  0x01,0x18,0xe9,0xa1,0x0f,0x00,0x00,0x48,0x00,0x84,0x23,0x90,0xe6,0xd3,0xf8,0x20,                  out_uint32_le(s, 0);
257  0xdb,0xa8,0x1b,0xb2,0xd0,0x78,0x2c,0x35,0xde,0xe3,0x0e,0x63,0x40,0xca,0xac,0x71,                  
258  0xc9,0x17,0x49,0x05,0x25,0xeb,0x9b,0xd0,0xa6,0x5c,0x90,0x3e,0x9d,0x4b,0x27,0x01,                  rdp_out_unistr(s, "GTB, sommartid",
259  0x79,0x1c,0x22,0xfb,0x3c,0x2c,0xb9,0x9f,0xf5,0x21,0xf3,0xee,0xd5,0x4d,0x47,0x1c,                                 2*strlen("GTB, sommartid"));
260  0x85,0xbe,0x83,0x93,0xe8,0xed,0x8c,0x5c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                  out_uint8s(s, 62-2*strlen("GTB, sommartid"));
261  0x00,0x01,0x00,0x10,0x04,0x30,0x82,0x04,0x0c,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,  
262  0x0d,0x01,0x07,0x02,0xa0,0x82,0x03,0xfd,0x30,0x82,0x03,0xf9,0x02,0x01,0x01,0x31,                  out_uint32_le(s, 0x30000);
263  0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,                  out_uint32_le(s, 0x050000);
264  0x03,0xe1,0x30,0x82,0x01,0x77,0x30,0x82,0x01,0x25,0xa0,0x03,0x02,0x01,0x02,0x02,                  out_uint32_le(s, 2);
265  0x08,0x01,0xbf,0x06,0x84,0x9d,0xdb,0x2d,0xe0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,                  out_uint32(s, 0);
266  0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x30,0x38,0x31,0x36,0x30,0x11,0x06,0x03,                  out_uint32_le(s, 0xffffffc4);
267  0x55,0x04,0x03,0x1e,0x0a,0x00,0x4e,0x00,0x54,0x00,0x54,0x00,0x53,0x00,0x45,0x30,                  out_uint32_le(s, 0xfffffffe);
268  0x21,0x06,0x03,0x55,0x04,0x07,0x1e,0x1a,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,                  out_uint32_le(s, 0x0f);
269  0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,0x00,0x63,0x00,0x6f,                  out_uint32(s, 0);
270  0x00,0x6d,0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x39,0x32,0x34,0x31,0x32,0x30,0x32,  
271  0x30,0x34,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x31,0x32,0x30,0x32,0x30,  
272  0x34,0x5a,0x30,0x38,0x31,0x36,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x1e,0x0a,0x00,          }
273  0x4e,0x00,0x54,0x00,0x54,0x00,0x53,0x00,0x45,0x30,0x21,0x06,0x03,0x55,0x04,0x07,          s_mark_end(s);
274  0x1e,0x1a,0x00,0x4d,0x00,0x69,0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,          sec_send(s, sec_flags);
275  0x00,0x66,0x00,0x74,0x00,0x2e,0x00,0x63,0x00,0x6f,0x00,0x6d,0x30,0x5c,0x30,0x0d,  }
276  0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,  
277  0x30,0x48,0x02,0x41,0x00,0x91,0xb2,0x16,0x1c,0xae,0x4f,0x7f,0x7c,0xaf,0x57,0x2b,  /* Send a control PDU */
278  0x23,0x4c,0x0c,0x25,0x3c,0x4f,0x66,0x9d,0x25,0xc3,0x4f,0x29,0xee,0x8b,0xda,0x4e,  static void
279  0x95,0xe7,0x3b,0xaa,0xc0,0xa7,0xba,0xaf,0x99,0x8c,0x47,0x24,0x8b,0x09,0x77,0xbc,  rdp_send_control(uint16 action)
280  0x2c,0xf4,0xe7,0x1a,0x07,0x58,0x7b,0x11,0x37,0x2a,0xa8,0x90,0xc3,0x50,0x92,0x80,  {
281  0x15,0xc5,0xda,0x51,0x8b,0x02,0x03,0x01,0x00,0x01,0xa3,0x13,0x30,0x11,0x30,0x0f,          STREAM s;
282  0x06,0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x00,0x30,  
283  0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x41,0x00,0x14,0x04,0x67,          s = rdp_init_data(8);
284  0x28,0xc8,0xd3,0x1f,0x13,0x14,0x2e,0x2c,0x93,0x09,0x25,0xbb,0xbe,0x86,0x6a,0xd3,  
285  0x47,0x6f,0x44,0x16,0x7b,0x94,0x8c,0xb2,0xa2,0xd5,0xf7,0x4f,0xb1,0x8f,0x7f,0xde,          out_uint16_le(s, action);
286  0x0b,0x88,0x34,0x4a,0x1d,0xdc,0xa1,0xfd,0x26,0xbd,0x43,0xbb,0x38,0xf1,0x87,0x34,          out_uint16(s, 0);       /* userid */
287  0xbb,0xe9,0x3b,0xfa,0x7f,0x1e,0xff,0xe1,0x10,0x7e,0xee,0x6e,0xd8,0x30,0x82,0x02,          out_uint32(s, 0);       /* control id */
288  0x62,0x30,0x82,0x02,0x10,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x01,0x00,0x00,0x00,  
289  0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x38,0x31,0x36,          s_mark_end(s);
290  0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x1e,0x0a,0x00,0x4e,0x00,0x54,0x00,0x54,0x00,          rdp_send_data(s, RDP_DATA_PDU_CONTROL);
291  0x53,0x00,0x45,0x30,0x21,0x06,0x03,0x55,0x04,0x07,0x1e,0x1a,0x00,0x4d,0x00,0x69,  }
292  0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,  
293  0x00,0x63,0x00,0x6f,0x00,0x6d,0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x39,0x32,0x34,  /* Send a synchronisation PDU */
294  0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x30,  static void
295  0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x79,0x31,0x77,0x30,0x17,0x06,0x03,0x55,0x04,  rdp_send_synchronise(void)
296  0x03,0x1e,0x10,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x37,0x00,0x2d,0x00,0x4e,0x00,  {
297  0x45,0x00,0x57,0x30,0x17,0x06,0x03,0x55,0x04,0x07,0x1e,0x10,0x00,0x7a,0x00,0x32,          STREAM s;
298  0x00,0x32,0x00,0x33,0x00,0x32,0x00,0x32,0x00,0x30,0x00,0x33,0x30,0x43,0x06,0x03,  
299  0x55,0x04,0x05,0x1e,0x3c,0x00,0x31,0x00,0x42,0x00,0x63,0x00,0x4b,0x00,0x65,0x00,          s = rdp_init_data(4);
300  0x57,0x00,0x50,0x00,0x6c,0x00,0x37,0x00,0x58,0x00,0x47,0x00,0x61,0x00,0x73,0x00,  
301  0x38,0x00,0x4a,0x00,0x79,0x00,0x50,0x00,0x34,0x00,0x30,0x00,0x7a,0x00,0x49,0x00,          out_uint16_le(s, 1);    /* type */
302  0x6d,0x00,0x6e,0x00,0x6f,0x00,0x51,0x00,0x5a,0x00,0x59,0x00,0x3d,0x00,0x0d,0x00,          out_uint16_le(s, 1002);
303  0x0a,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,  
304  0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0x91,0xb2,0x16,0x1c,0xae,0x4f,          s_mark_end(s);
305  0x7f,0x7c,0xaf,0x57,0x2b,0x23,0x4c,0x0c,0x25,0x3c,0x4f,0x66,0x9d,0x25,0xc3,0x4f,          rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
306  0x29,0xee,0x8b,0xda,0x4e,0x95,0xe7,0x3b,0xaa,0xc0,0xa7,0xba,0xaf,0x99,0x8c,0x47,  }
307  0x24,0x8b,0x09,0x77,0xbc,0x2c,0xf4,0xe7,0x1a,0x07,0x58,0x7b,0x11,0x37,0x2a,0xa8,  
308  0x90,0xc3,0x50,0x92,0x80,0x15,0xc5,0xda,0x51,0x8b,0x02,0x03,0x01,0x00,0x01,0xa3,  /* Send a single input event */
309  0x81,0xc3,0x30,0x81,0xc0,0x30,0x14,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,  void
310  0x12,0x04,0x01,0x01,0xff,0x04,0x04,0x01,0x00,0x01,0x00,0x30,0x3c,0x06,0x09,0x2b,  rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
311  0x06,0x01,0x04,0x01,0x82,0x37,0x12,0x02,0x01,0x01,0xff,0x04,0x2c,0x4d,0x00,0x69,  {
312  0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,          STREAM s;
313  0x00,0x43,0x00,0x6f,0x00,0x72,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x74,  
314  0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x30,0x4c,0x06,0x09,0x2b,0x06,0x01,          s = rdp_init_data(16);
315  0x04,0x01,0x82,0x37,0x12,0x05,0x01,0x01,0xff,0x04,0x3c,0x00,0x10,0x00,0x00,0x01,  
316  0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x18,0x00,0x18,0x00,0x30,          out_uint16_le(s, 1);    /* number of events */
317  0x00,0x01,0x00,0x32,0x00,0x33,0x00,0x36,0x00,0x2d,0x00,0x34,0x00,0x2e,0x00,0x30,          out_uint16(s, 0);       /* pad */
318  0x00,0x30,0x00,0x2d,0x00,0x45,0x00,0x58,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,  
319  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x1c,0x06,0x03,0x55,0x1d,0x23,0x01,0x01,          out_uint32_le(s, time);
320  0xff,0x04,0x12,0x30,0x10,0xa1,0x07,0x81,0x05,0x4e,0x54,0x54,0x53,0x45,0x82,0x05,          out_uint16_le(s, message_type);
321  0x01,0x00,0x00,0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,          out_uint16_le(s, device_flags);
322  0x03,0x41,0x00,0x7b,0x1d,0xfd,0x24,0xea,0xf2,0xe8,0x17,0xdd,0x88,0x7e,0xfd,0xee,          out_uint16_le(s, param1);
323  0x28,0x61,0x7a,0x02,0xc3,0x73,0xcf,0x32,0x0f,0x7c,0x66,0x87,0x31,0xa7,0xbe,0x1b,          out_uint16_le(s, param2);
324  0x31,0xe2,0x20,0xa5,0x76,0x91,0x68,0x97,0x53,0x9e,0x80,0xcd,0x2b,0xd0,0x8e,0x8b,  
325  0x7f,0x89,0x1b,0x62,0xa8,0xf8,0xee,0x5e,0x56,0xbd,0x9c,0x6b,0x80,0x06,0x54,0xd3,          s_mark_end(s);
326  0xf0,0xbf,0xb2,0x31,0x00,0x01,0x00,0x14,0x00,0xc7,0x32,0xf2,0x5b,0x98,0x0e,0x04,          rdp_send_data(s, RDP_DATA_PDU_INPUT);
327  0x49,0xa0,0x27,0x7e,0xf5,0xf6,0x0f,0xda,0x08,0x1d,0xe9,0x79,0xd1,0x31,0xc6,0x50,  }
328  0x90,0x4a,0xd3,0x1f,0x1d,0xf0,0x65,0x0d,0xb6,0x1f,0xaf,0xc9,0x1d  
329    /* Send an (empty) font information PDU */
330    static void
331    rdp_send_fonts(uint16 seq)
332    {
333            STREAM s;
334    
335            s = rdp_init_data(8);
336    
337            out_uint16(s, 0);       /* number of fonts */
338            out_uint16_le(s, 0x3e); /* unknown */
339            out_uint16_le(s, seq);  /* unknown */
340            out_uint16_le(s, 0x32); /* entry size */
341    
342            s_mark_end(s);
343            rdp_send_data(s, RDP_DATA_PDU_FONT2);
344    }
345    
346    /* Output general capability set */
347    static void
348    rdp_out_general_caps(STREAM s)
349    {
350            out_uint16_le(s, RDP_CAPSET_GENERAL);
351            out_uint16_le(s, RDP_CAPLEN_GENERAL);
352    
353            out_uint16_le(s, 1);    /* OS major type */
354            out_uint16_le(s, 3);    /* OS minor type */
355            out_uint16_le(s, 0x200);        /* Protocol version */
356            out_uint16(s, 0);       /* Pad */
357            out_uint16(s, 0);       /* Compression types */
358            out_uint16_le(s, use_rdp5 ? 0x40d : 0);
359            /* Pad, according to T.128. 0x40d seems to
360               trigger
361               the server to start sending RDP5 packets.
362               However, the value is 0x1d04 with W2KTSK and
363               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
364               for sending such information in a padding
365               field.. */
366            out_uint16(s, 0);       /* Update capability */
367            out_uint16(s, 0);       /* Remote unshare capability */
368            out_uint16(s, 0);       /* Compression level */
369            out_uint16(s, 0);       /* Pad */
370    }
371    
372    /* Output bitmap capability set */
373    static void
374    rdp_out_bitmap_caps(STREAM s)
375    {
376            out_uint16_le(s, RDP_CAPSET_BITMAP);
377            out_uint16_le(s, RDP_CAPLEN_BITMAP);
378    
379            out_uint16_le(s, 8);    /* Preferred BPP */
380            out_uint16_le(s, 1);    /* Receive 1 BPP */
381            out_uint16_le(s, 1);    /* Receive 4 BPP */
382            out_uint16_le(s, 1);    /* Receive 8 BPP */
383            out_uint16_le(s, 800);  /* Desktop width */
384            out_uint16_le(s, 600);  /* Desktop height */
385            out_uint16(s, 0);       /* Pad */
386            out_uint16(s, 0);       /* Allow resize */
387            out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */
388            out_uint16(s, 0);       /* Unknown */
389            out_uint16_le(s, 1);    /* Unknown */
390            out_uint16(s, 0);       /* Pad */
391    }
392    
393    /* Output order capability set */
394    static void
395    rdp_out_order_caps(STREAM s)
396    {
397            uint8 order_caps[32];
398    
399    
400            memset(order_caps, 0, 32);
401            order_caps[0] = 1;      /* dest blt */
402            order_caps[1] = 1;      /* pat blt */
403            order_caps[2] = 1;      /* screen blt */
404            order_caps[3] = 1;      /* required for memblt? */
405            order_caps[8] = 1;      /* line */
406            order_caps[9] = 1;      /* line */
407            order_caps[10] = 1;     /* rect */
408            order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */
409            order_caps[13] = 1;     /* memblt */
410            order_caps[14] = 1;     /* triblt */
411            order_caps[22] = 1;     /* polyline */
412            order_caps[27] = 1;     /* text2 */
413            out_uint16_le(s, RDP_CAPSET_ORDER);
414            out_uint16_le(s, RDP_CAPLEN_ORDER);
415    
416            out_uint8s(s, 20);      /* Terminal desc, pad */
417            out_uint16_le(s, 1);    /* Cache X granularity */
418            out_uint16_le(s, 20);   /* Cache Y granularity */
419            out_uint16(s, 0);       /* Pad */
420            out_uint16_le(s, 1);    /* Max order level */
421            out_uint16_le(s, 0x147);        /* Number of fonts */
422            out_uint16_le(s, 0x2a); /* Capability flags */
423            out_uint8p(s, order_caps, 32);  /* Orders supported */
424            out_uint16_le(s, 0x6a1);        /* Text capability flags */
425            out_uint8s(s, 6);       /* Pad */
426            out_uint32_le(s, desktop_save == False ? 0 : 0x38400);  /* Desktop cache size */
427            out_uint32(s, 0);       /* Unknown */
428            out_uint32_le(s, 0x4e4);        /* Unknown */
429    }
430    
431    /* Output bitmap cache capability set */
432    static void
433    rdp_out_bmpcache_caps(STREAM s)
434    {
435            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
436            out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
437    
438            out_uint8s(s, 24);      /* unused */
439            out_uint16_le(s, 0x258);        /* entries */
440            out_uint16_le(s, 0x100);        /* max cell size */
441            out_uint16_le(s, 0x12c);        /* entries */
442            out_uint16_le(s, 0x400);        /* max cell size */
443            out_uint16_le(s, 0x106);        /* entries */
444            out_uint16_le(s, 0x1000);       /* max cell size */
445    }
446    
447    /* Output control capability set */
448    static void
449    rdp_out_control_caps(STREAM s)
450    {
451            out_uint16_le(s, RDP_CAPSET_CONTROL);
452            out_uint16_le(s, RDP_CAPLEN_CONTROL);
453    
454            out_uint16(s, 0);       /* Control capabilities */
455            out_uint16(s, 0);       /* Remote detach */
456            out_uint16_le(s, 2);    /* Control interest */
457            out_uint16_le(s, 2);    /* Detach interest */
458    }
459    
460    /* Output activation capability set */
461    static void
462    rdp_out_activate_caps(STREAM s)
463    {
464            out_uint16_le(s, RDP_CAPSET_ACTIVATE);
465            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
466    
467            out_uint16(s, 0);       /* Help key */
468            out_uint16(s, 0);       /* Help index key */
469            out_uint16(s, 0);       /* Extended help key */
470            out_uint16(s, 0);       /* Window activate */
471    }
472    
473    /* Output pointer capability set */
474    static void
475    rdp_out_pointer_caps(STREAM s)
476    {
477            out_uint16_le(s, RDP_CAPSET_POINTER);
478            out_uint16_le(s, RDP_CAPLEN_POINTER);
479    
480            out_uint16(s, 0);       /* Colour pointer */
481            out_uint16_le(s, 20);   /* Cache size */
482    }
483    
484    /* Output share capability set */
485    static void
486    rdp_out_share_caps(STREAM s)
487    {
488            out_uint16_le(s, RDP_CAPSET_SHARE);
489            out_uint16_le(s, RDP_CAPLEN_SHARE);
490    
491            out_uint16(s, 0);       /* userid */
492            out_uint16(s, 0);       /* pad */
493    }
494    
495    /* Output colour cache capability set */
496    static void
497    rdp_out_colcache_caps(STREAM s)
498    {
499            out_uint16_le(s, RDP_CAPSET_COLCACHE);
500            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
501    
502            out_uint16_le(s, 6);    /* cache size */
503            out_uint16(s, 0);       /* pad */
504    }
505    
506    static uint8 canned_caps[] = {
507            0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
508            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
509            0x00, 0x00, 0x00, 0x00, 0x00,
510            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
511            0x00, 0x00, 0x00, 0x00, 0x00,
512            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
513            0x00, 0x00, 0x00, 0x00, 0x00,
514            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
515            0x00, 0x00, 0x00, 0x00, 0x00,
516            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
517            0x0C, 0x00, 0x08, 0x00, 0x01,
518            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
519            0x10, 0x00, 0x34, 0x00, 0xFE,
520            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
521            0xFE, 0x00, 0x08, 0x00, 0xFE,
522            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
523            0xFE, 0x00, 0x80, 0x00, 0xFE,
524            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
525            0x02, 0x00, 0x00, 0x00
526  };  };
527    
528  /* Send license certificate and related data to the server */  /* Output unknown capability sets (number 13, 12, 14 and 16) */
529  void rdp_send_cert(HCONN conn)  static void
530  {  rdp_out_unknown_caps(STREAM s)
531          mcs_init_data(conn);  {
532          prs_io_uint8s(&conn->out, precanned_cert_packet, sizeof(precanned_cert_packet));          out_uint16_le(s, RDP_CAPSET_UNKNOWN);
533          MARK_END(conn->out);          out_uint16_le(s, 0x58);
534          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
535  }          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
536    }
537  /* Initialise RDP transport packet */  
538  void rdp_init(HCONN conn)  #define RDP5_FLAG 0x0030
539  {  /* Send a confirm active PDU */
540          mcs_init_data(conn);  static void
541          PUSH_LAYER(conn->out, rdp_offset, 6);  rdp_send_confirm_active(void)
542  }  {
543            STREAM s;
544  /* Transmit RDP transport packet */          uint32 sec_flags = encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
545  void rdp_send(HCONN conn, uint16 pdu_type)          uint16 caplen =
546  {                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
547          RDP_HEADER hdr;                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
548          int length;                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
549                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
550          POP_LAYER(conn->out, rdp_offset);  
551          length = conn->out.end - conn->out.offset;          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
552          rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);  
553          rdp_io_header(&conn->out, &hdr);          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
554          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
555  }          out_uint16_le(s, (g_mcs_userid + 1001));
556    
557  /* Initialise RDP transport data packet */          out_uint32_le(s, rdp_shareid);
558  void rdp_init_data(HCONN conn)          out_uint16_le(s, 0x3ea);        /* userid */
559  {          out_uint16_le(s, sizeof(RDP_SOURCE));
560          mcs_init_data(conn);          out_uint16_le(s, caplen);
561          PUSH_LAYER(conn->out, rdp_offset, 18);  
562  }          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
563            out_uint16_le(s, 0xd);  /* num_caps */
564  /* Transmit RDP transport data packet */          out_uint8s(s, 2);       /* pad */
565  void rdp_send_data(HCONN conn, uint16 data_pdu_type)  
566  {          rdp_out_general_caps(s);
567          RDP_HEADER hdr;          rdp_out_bitmap_caps(s);
568          RDP_DATA_HEADER datahdr;          rdp_out_order_caps(s);
569          int length = conn->out.end - conn->out.offset;          rdp_out_bmpcache_caps(s);
570            rdp_out_colcache_caps(s);
571          POP_LAYER(conn->out, rdp_offset);          rdp_out_activate_caps(s);
572          length = conn->out.end - conn->out.offset;          rdp_out_control_caps(s);
573          rdp_make_header(&hdr, length, RDP_PDU_DATA, conn->mcs_userid);          rdp_out_pointer_caps(s);
574          rdp_io_header(&conn->out, &hdr);          rdp_out_share_caps(s);
575          rdp_make_data_header(&datahdr, 0x103ea, length, data_pdu_type);          rdp_out_unknown_caps(s);
576          rdp_io_data_header(&conn->out, &datahdr);  
577          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);          s_mark_end(s);
578  }          sec_send(s, sec_flags);
579    }
580  void rdp_send_confirm_active(HCONN conn)  
581  {  /* Respond to a demand active PDU */
582          RDP_ACTIVE_PDU active;  static void
583    process_demand_active(STREAM s)
         rdp_init(conn);  
         rdp_make_active_pdu(&active, 0x103ea, conn->mcs_userid);  
         rdp_io_active_pdu(&conn->out, &active, RDP_PDU_CONFIRM_ACTIVE);  
         MARK_END(conn->out);  
         rdp_send(conn, RDP_PDU_CONFIRM_ACTIVE);  
 }  
   
 void rdp_send_synchronize(HCONN conn)  
 {  
         RDP_SYNCHRONIZE_PDU sync;  
   
         rdp_init_data(conn);  
         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);  
 }  
   
 void rdp_send_control(HCONN conn, uint16 action)  
 {  
         RDP_CONTROL_PDU control;  
   
         rdp_init_data(conn);  
         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);  
 }  
   
 void rdp_send_fonts(HCONN conn, uint16 seqno)  
 {  
         RDP_FONT_PDU fonts;  
   
         rdp_init_data(conn);  
         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);  
 }  
   
 void rdp_send_input(HCONN conn)  
 {  
         RDP_INPUT_PDU input;  
   
         rdp_init_data(conn);  
         rdp_make_input_pdu(&input);  
         rdp_io_input_pdu(&conn->out, &input);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_INPUT);  
 }  
   
 BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  
 {  
         RDP_HEADER hdr;  
   
         if (!mcs_recv(conn, False) || !rdp_io_header(&conn->in, &hdr))  
                 return False;  
   
         *type = hdr.pdu_type & 0xf;  
         return True;  
 }  
   
 /* Disconnect from the RDP layer */  
 void rdp_disconnect(HCONN conn)  
 {  
         mcs_disconnect(conn);  
 }  
   
 void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,  
                      uint16 userid)  
 {  
         hdr->length = length;  
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
 }  
   
 void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,  
                           uint16 length, uint16 data_pdu_type)  
 {  
         hdr->shareid = shareid;  
         hdr->pad = 0;  
         hdr->streamid = 1;  
         hdr->length = length - 14;  
         hdr->data_pdu_type = data_pdu_type;  
         hdr->compress_type = 0;  
         hdr->compress_len = 0;  
 }  
   
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
   
 void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps)  
 {  
         caps->preferred_bpp = 8;  
         caps->receive1bpp = 1;  
         caps->receive4bpp = 1;  
         caps->receive8bpp = 1;  
         caps->width = 640;  
         caps->height = 480;  
         caps->compression = 1;  
         caps->unknown2 = 1;  
 }  
   
 void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  
584  {  {
585          caps->xgranularity = 1;          uint8 type;
         caps->ygranularity = 20;  
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
   
 //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;  
   
         caps->support[0] = caps->support[1] = caps->support[2]  
                 = 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;  
 }  
   
 void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  
 {  
         caps->caches[0].entries = 0x258;  
         caps->caches[0].max_cell_size = 0x100;  
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
 }  
   
 void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)  
 {  
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
586    
587  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)          in_uint32_le(s, rdp_shareid);
 {  
 }  
588    
589  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));
 {  
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
590    
591  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)          rdp_send_confirm_active();
592  {          rdp_send_synchronise();
593            rdp_send_control(RDP_CTL_COOPERATE);
594            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
595            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
596            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
597            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
598            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
599            rdp_send_fonts(1);
600            rdp_send_fonts(2);
601            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
602            reset_order_state();
603  }  }
604    
605  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  /* Process a null system pointer PDU */
606    void
607    process_null_system_pointer_pdu(STREAM s)
608  {  {
609          caps->cache_size = 6;          // FIXME: We should probably set another cursor here,
610            // like the X window system base cursor or something.
611            ui_set_cursor(cache_get_cursor(0));
612  }  }
613    
614  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid)  /* Process a colour pointer PDU */
615    void
616    process_colour_pointer_pdu(STREAM s)
617  {  {
618          memset(pdu, 0, sizeof(*pdu));          uint16 x, y, width, height, cache_idx, masklen, datalen;
619          pdu->shareid = shareid;          uint8 *mask, *data;
620          pdu->userid  = 1002;          HCURSOR cursor;
         pdu->source_len = sizeof(RDP_SOURCE);  
         memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));  
621    
622          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          in_uint16_le(s, cache_idx);
623                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          in_uint16_le(s, x);
624                  + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE          in_uint16_le(s, y);
625                  + RDP_CAPLEN_UNKNOWN;          in_uint16_le(s, width);
626          pdu->num_caps = 0xD;          in_uint16_le(s, height);
627            in_uint16_le(s, masklen);
628          rdp_make_general_caps (&pdu->general_caps );          in_uint16_le(s, datalen);
629          rdp_make_bitmap_caps  (&pdu->bitmap_caps  );          in_uint8p(s, data, datalen);
630          rdp_make_order_caps   (&pdu->order_caps   );          in_uint8p(s, mask, masklen);
631          rdp_make_bmpcache_caps(&pdu->bmpcache_caps);          cursor = ui_create_cursor(x, y, width, height, mask, data);
632          rdp_make_control_caps (&pdu->control_caps );          ui_set_cursor(cursor);
633          rdp_make_activate_caps(&pdu->activate_caps);          cache_put_cursor(cache_idx, cursor);
         rdp_make_pointer_caps (&pdu->pointer_caps );  
         rdp_make_share_caps   (&pdu->share_caps, userid);  
         rdp_make_colcache_caps(&pdu->colcache_caps);  
634  }  }
635    
636  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  /* Process a cached pointer PDU */
637    void
638    process_cached_pointer_pdu(STREAM s)
639  {  {
640          pdu->action = action;          uint16 cache_idx;
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
   
 void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid)  
 {  
         pdu->type = 1;  
         pdu->userid = userid;  
 }  
641    
642  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          in_uint16_le(s, cache_idx);
643  {          ui_set_cursor(cache_get_cursor(cache_idx));
         pdu->num_fonts = 0;  
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
644  }  }
645    
 void rdp_make_input_pdu(RDP_INPUT_PDU *pdu)  
 {  
         uint32 now = time(NULL);  
   
         pdu->num_events = 3;  
         pdu->pad = 0;  
   
         pdu->event[0].event_time = now;  
         pdu->event[0].message_type = RDP_INPUT_SYNCHRONIZE;  
         pdu->event[0].device_flags = 0;  
         pdu->event[0].mouse_x = 0;  
         pdu->event[0].mouse_y = 0;  
   
         pdu->event[1].event_time = now;  
         pdu->event[1].message_type = RDP_INPUT_UNKNOWN;  
         pdu->event[1].device_flags = 0x8000;  
         pdu->event[1].mouse_x = 15;  
         pdu->event[1].mouse_y = 0;  
646    
647          pdu->event[2].event_time = now;  /* Process a pointer PDU */
648          pdu->event[2].message_type = RDP_INPUT_MOUSE;  static void
649          pdu->event[2].device_flags = MOUSE_FLAG_MOVE;  process_pointer_pdu(STREAM s)
         pdu->event[2].mouse_x = 425;  
         pdu->event[2].mouse_y = 493;  
 }  
   
 BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  
650  {  {
651          BOOL res = True;          uint16 message_type;
652            uint16 x, y;
653    
654          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          in_uint16_le(s, message_type);
655          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          in_uint8s(s, 2);        /* pad */
         res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;  
656    
657          return res;          switch (message_type)
658  }          {
659                    case RDP_POINTER_MOVE:
660                            in_uint16_le(s, x);
661                            in_uint16_le(s, y);
662                            if (s_check(s))
663                                    ui_move_pointer(x, y);
664                            break;
665    
666  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)                  case RDP_POINTER_COLOR:
667  {                          process_colour_pointer_pdu(s);
668          BOOL res = True;                          break;
669    
670          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;                  case RDP_POINTER_CACHED:
671          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;                          process_cached_pointer_pdu(s);
672          res = res ? prs_io_uint8 (s, &hdr->streamid     ) : False;                          break;
         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;  
673    
674          return res;                  default:
675                            DEBUG(("Pointer message 0x%x\n", message_type));
676            }
677  }  }
678    
679  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  /* Process bitmap updates */
680    void
681    process_bitmap_updates(STREAM s)
682  {  {
683          uint16 length = RDP_CAPLEN_GENERAL;          uint16 num_updates;
684          uint16 pkt_length = length;          uint16 left, top, right, bottom, width, height;
685          BOOL res;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
686            uint8 *data, *bmpdata;
687          res = lsb_io_uint16(s, &pkt_length);          int i;
         if (pkt_length != length)  
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
688    
689          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          in_uint16_le(s, num_updates);
         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;  
690    
691          res = lsb_io_uint16(s, &pkt_length);          for (i = 0; i < num_updates; i++)
         if (pkt_length != length)  
692          {          {
693                  fprintf(stderr, "Unrecognised capabilities size\n");                  in_uint16_le(s, left);
694                  return False;                  in_uint16_le(s, top);
695          }                  in_uint16_le(s, right);
696                    in_uint16_le(s, bottom);
697          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  in_uint16_le(s, width);
698          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;                  in_uint16_le(s, height);
699          res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;                  in_uint16_le(s, bpp);
700          res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;                  Bpp = (bpp + 7) / 8;
701          res = res ? lsb_io_uint16(s, &caps->width        ) : False;                  in_uint16_le(s, compress);
702          res = res ? lsb_io_uint16(s, &caps->height       ) : False;                  in_uint16_le(s, bufsize);
         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;  
703    
704          res = lsb_io_uint16(s, &pkt_length);                  cx = right - left + 1;
705          if (pkt_length != length)                  cy = bottom - top + 1;
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
706    
707          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
708          res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;                         left, top, right, bottom, width, height, Bpp, compress));
         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;  
709    
710          return res;                  if (!compress)
711  }                  {
712                            int y;
713                            bmpdata = (uint8*)xmalloc(width * height * Bpp);
714                            for (y = 0; y < height; y++)
715                            {
716                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
717                                              width * Bpp);
718                            }
719                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
720                            xfree(bmpdata);
721                            continue;
722                    }
723    
 BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  
 {  
         if (!lsb_io_uint16(s, &info->entries      ))  
                 return False;  
724    
725          if (!lsb_io_uint16(s, &info->max_cell_size))                  if (compress & 0x400)
726                  return False;                  {
727                            size = bufsize;
728                    }
729                    else
730                    {
731                            in_uint8s(s, 2);        /* pad */
732                            in_uint16_le(s, size);
733                            in_uint8s(s, 4);        /* line_size, final_size */
734                    }
735                    in_uint8p(s, data, size);
736                    bmpdata = (uint8*)xmalloc(width * height * Bpp);
737                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
738                    {
739                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
740                    }
741                    else
742                    {
743                            DEBUG_RDP5(("Failed to decompress data\n"));
744                    }
745    
746          return True;                  xfree(bmpdata);
747            }
748  }  }
749    
750  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  /* Process a palette update */
751    void
752    process_palette(STREAM s)
753  {  {
754          uint16 length = RDP_CAPLEN_BMPCACHE;          COLOURENTRY *entry;
755          uint16 pkt_length = length;          COLOURMAP map;
756          BOOL res;          HCOLOURMAP hmap;
757          int i;          int i;
758    
759          res = lsb_io_uint16(s, &pkt_length);          in_uint8s(s, 2);        /* pad */
760          if (pkt_length != length)          in_uint16_le(s, map.ncolours);
761          {          in_uint8s(s, 2);        /* pad */
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         for (i = 0; i < 6; i++)  
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
   
         for (i = 0; i < 3; i++)  
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
762    
763          return res;          map.colours = (COLOURENTRY*)xmalloc(3 * map.ncolours);
 }  
764    
765  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
766    
767          res = lsb_io_uint16(s, &pkt_length);          for (i = 0; i < map.ncolours; i++)
         if (pkt_length != length)  
768          {          {
769                  fprintf(stderr, "Unrecognised capabilities size\n");                  entry = &map.colours[i];
770                  return False;                  in_uint8(s, entry->red);
771                    in_uint8(s, entry->green);
772                    in_uint8(s, entry->blue);
773          }          }
774    
775          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;          hmap = ui_create_colourmap(&map);
776          res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;          ui_set_colourmap(hmap);
         res = res ? lsb_io_uint16(s, &caps->control_interest) : False;  
         res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  
777    
778          return res;          xfree(map.colours);
779  }  }
780    
781  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  /* Process an update PDU */
782    static void
783    process_update_pdu(STREAM s)
784  {  {
785          uint16 length = RDP_CAPLEN_ACTIVATE;          uint16 update_type, count;
         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;  
         }  
   
         res = res ? lsb_io_uint16(s, &caps->help_key         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_index_key   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_extended_key) : False;  
         res = res ? lsb_io_uint16(s, &caps->window_activate  ) : False;  
   
         return res;  
 }  
786    
787  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)          in_uint16_le(s, update_type);
 {  
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
788    
789          res = lsb_io_uint16(s, &pkt_length);          switch (update_type)
         if (pkt_length != length)  
790          {          {
791                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_UPDATE_ORDERS:
792                  return False;                          in_uint8s(s, 2);        /* pad */
793          }                          in_uint16_le(s, count);
794                            in_uint8s(s, 2);        /* pad */
795                            process_orders(s, count);
796                            break;
797    
798          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_UPDATE_BITMAP:
799          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          process_bitmap_updates(s);
800                            break;
801    
802          return res;                  case RDP_UPDATE_PALETTE:
803  }                          process_palette(s);
804                            break;
805    
806  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                  case RDP_UPDATE_SYNCHRONIZE:
807  {                          break;
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
808    
809          res = lsb_io_uint16(s, &pkt_length);                  default:
810          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
811          }          }
812    
         res = res ? lsb_io_uint16(s, &caps->userid) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad   ) : False;  
   
         return res;  
813  }  }
814    
815  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  /* Process data PDU */
816    static void
817    process_data_pdu(STREAM s)
818  {  {
819          uint16 length = RDP_CAPLEN_COLCACHE;          uint8 data_pdu_type;
         uint16 pkt_length = length;  
         BOOL res;  
820    
821          res = lsb_io_uint16(s, &pkt_length);          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
822          if (pkt_length != length)          in_uint8(s, data_pdu_type);
823          {          in_uint8s(s, 3);        /* compress_type, compress_len */
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
         }  
824    
825          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          switch (data_pdu_type)
826          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          {
827                    case RDP_DATA_PDU_UPDATE:
828                            process_update_pdu(s);
829                            break;
830    
831          return res;                  case RDP_DATA_PDU_POINTER:
832  }                          process_pointer_pdu(s);
833                            break;
834    
835  uint8 canned_caps[] = {                  case RDP_DATA_PDU_BELL:
836  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,                          ui_bell();
837  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                          break;
 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  
 };  
838    
839  BOOL rdp_io_unknown_caps(STREAM s, void *caps)                  case RDP_DATA_PDU_LOGON:
840  {                          DEBUG(("Received Logon PDU\n"));
841          uint16 length = 0x58;                          /* User logged on */
842          uint16 pkt_length = length;                          break;
         BOOL res;  
843    
844          res = lsb_io_uint16(s, &pkt_length);                  default:
845          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
846          }          }
   
         res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;  
   
         return res;  
847  }  }
848    
849  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  /* Process incoming packets */
850    void
851    rdp_main_loop(void)
852  {  {
853          uint16 capset;          uint8 type;
854          uint16 length;          STREAM s;
         BOOL res;  
         int i;  
   
         res = lsb_io_uint32(s, &pdu->shareid);  
   
         if (pdutype == RDP_PDU_CONFIRM_ACTIVE)  
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
   
         res = res ? lsb_io_uint16(s, &pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
   
         if (pdu->source_len > 48)  
         {  
                 fprintf(stderr, "RDP source descriptor too long\n");  
                 return False;  
         }  
855    
856          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          while ((s = rdp_recv(&type)) != NULL)
         res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;  
         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  
857          {          {
858                  for (i = 0; i < pdu->num_caps; i++)                  switch (type)
859                  {                  {
860                          if (!res)                          case RDP_PDU_DEMAND_ACTIVE:
861                                  return False;                                  process_demand_active(s);
   
                         if (!lsb_io_uint16(s, &capset))  
                                 return False;  
   
                         switch (capset)  
                         {  
                         case RDP_CAPSET_GENERAL:  
                                 res = rdp_io_general_caps (s, &pdu->general_caps );  
                                 break;  
                         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);  
862                                  break;                                  break;
863                          case RDP_CAPSET_POINTER:  
864                                  res = rdp_io_pointer_caps (s, &pdu->pointer_caps );                          case RDP_PDU_DEACTIVATE:
                                 break;  
                         case RDP_CAPSET_SHARE:  
                                 res = rdp_io_share_caps   (s, &pdu->share_caps   );  
865                                  break;                                  break;
866                          case RDP_CAPSET_COLCACHE:  
867                                  res = rdp_io_colcache_caps(s, &pdu->colcache_caps);                          case RDP_PDU_DATA:
868                                    process_data_pdu(s);
869                                  break;                                  break;
                         default:  
                                 fprintf(stderr, "Warning: Unrecognised capset %x\n",  
                                         capset);  
870    
871                                  if (!lsb_io_uint16(s, &length))                          case 0:
872                                          return False;                                  break;
873    
874                                  s->offset += (length - 4);                          default:
875                          }                                  unimpl("PDU %d\n", type);
876                  }                  }
877          }          }
   
         return res;  
 }  
   
 BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint16(s, &pdu->action   ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;  
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint16(s, &pdu->type  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint32(s, &evt->event_time)   : False;  
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
   
         if (!res)  
                 return False;  
   
         switch (evt->message_type)  
         {  
         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;  
         }  
   
         return res;  
 }  
   
 BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  
 {  
         BOOL res = True;  
         int i;  
   
         res = res ? lsb_io_uint16(s, &pdu->num_events) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
   
         if (pdu->num_events > RDP_MAX_EVENTS)  
         {  
                 fprintf(stderr, "Too many events in one PDU\n");  
                 return False;  
         }  
   
         for (i = 0; i < pdu->num_events; i++)  
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
         }  
   
         return res;  
 }  
   
 BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  
 {  
         BOOL res = True;  
   
         res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;  
         res = res ? lsb_io_uint16(s, &font->flags    ) : False;  
         res = res ? lsb_io_uint16(s, &font->width    ) : False;  
         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;  
   
         return res;  
878  }  }
879    
880  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  /* Establish a connection up to the RDP layer */
881    BOOL
882    rdp_connect(char *server, uint32 flags, char *domain, char *password,
883                char *command, char *directory)
884  {  {
885          BOOL res = True;          if (!sec_connect(server, username))
         int i;  
   
         res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  
   
         if (pdu->num_fonts > RDP_MAX_FONTS)  
         {  
                 fprintf(stderr, "Too many fonts in one PDU\n");  
886                  return False;                  return False;
         }  
   
         for (i = 0; i < pdu->num_fonts; i++)  
         {  
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
         }  
   
         return res;  
 }  
   
 BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  
 {  
         BOOL res = True;  
887    
888          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;          rdp_send_logon_info(flags, domain, username, password, command, directory);
889          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;          return True;
   
         return res;  
 }  
   
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint16(s, &rso->length) : False;  
         res = res ? lsb_io_uint16(s, &rso->flags ) : False;  
         res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
   
         return res;  
890  }  }
891    
892  BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)  /* Disconnect from the RDP layer */
893    void
894    rdp_disconnect(void)
895  {  {
896          BOOL res = True;          sec_disconnect();
   
         res = res ? prs_io_uint8 (s, &rdh->cache_id  ) : False;  
         res = res ? prs_io_uint8 (s, &rdh->pad1      ) : False;  
         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;  
   
         return res;  
897  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26