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

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

  ViewVC Help
Powered by ViewVC 1.1.26