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

Legend:
Removed from v.7  
changed lines
  Added in v.365

  ViewVC Help
Powered by ViewVC 1.1.26