/[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 192 by matthewc, Tue Sep 24 07:59:14 2002 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_le(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) : SEC_LOGON_INFO;
159            STREAM s;
160    
161  void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,          s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
162                            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;  
 }  
163    
164  void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)          out_uint32(s, 0);
165  {          out_uint32_le(s, flags);
166          caps->os_major_type = 1;          out_uint16_le(s, len_domain);
167          caps->os_minor_type = 3;          out_uint16_le(s, len_user);
168          caps->ver_protocol = 0x200;          out_uint16_le(s, len_password);
169  }          out_uint16_le(s, len_program);
170            out_uint16_le(s, len_directory);
171            rdp_out_unistr(s, domain, len_domain);
172            rdp_out_unistr(s, user, len_user);
173            rdp_out_unistr(s, password, len_password);
174            rdp_out_unistr(s, program, len_program);
175            rdp_out_unistr(s, directory, len_directory);
176    
177  void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps)          s_mark_end(s);
178  {          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;  
179  }  }
180    
181  void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  /* Send a control PDU */
182    static void
183    rdp_send_control(uint16 action)
184  {  {
185          caps->xgranularity = 1;          STREAM s;
         caps->ygranularity = 20;  
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
186    
187  //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;          s = rdp_init_data(8);
188    
189          caps->support[0] = caps->support[1] = caps->support[2]          out_uint16_le(s, action);
190                  = caps->support[3] = caps->support[4] = caps->support[5]          out_uint16(s, 0);       /* userid */
191                  = 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;  
 }  
192    
193  void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)          s_mark_end(s);
194  {          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;  
195  }  }
196    
197  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)  /* Send a synchronisation PDU */
198    static void
199    rdp_send_synchronise(void)
200  {  {
201          caps->control_interest = 2;          STREAM s;
         caps->detach_interest = 2;  
 }  
202    
203  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;  
 }  
204    
205  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)          out_uint16_le(s, 1);    /* type */
206  {          out_uint16_le(s, 1002);
 }  
207    
208  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)          s_mark_end(s);
209  {          rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
         caps->cache_size = 6;  
210  }  }
211    
212  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid)  /* Send a single input event */
213    void
214    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
215  {  {
216          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));  
217    
218          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);  
 }  
219    
220  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)          out_uint16_le(s, 1);    /* number of events */
221  {          out_uint16(s, 0);       /* pad */
         pdu->action = action;  
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
222    
223  void rdp_make_synchronize_pdu(RDP_SYNCHRONIZE_PDU *pdu, uint16 userid)          out_uint32_le(s, time);
224  {          out_uint16_le(s, message_type);
225          pdu->type = 1;          out_uint16_le(s, device_flags);
226          pdu->userid = userid;          out_uint16_le(s, param1);
227  }          out_uint16_le(s, param2);
228    
229  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          s_mark_end(s);
230  {          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;  
231  }  }
232    
233  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu)  /* Send an (empty) font information PDU */
234    static void
235    rdp_send_fonts(uint16 seq)
236  {  {
237          uint32 now = time(NULL);          STREAM s;
   
         pdu->num_events = 3;  
         pdu->pad = 0;  
238    
239          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;  
240    
241          pdu->event[1].event_time = now;          out_uint16(s, 0);       /* number of fonts */
242          pdu->event[1].message_type = RDP_INPUT_UNKNOWN;          out_uint16_le(s, 0x3e); /* unknown */
243          pdu->event[1].device_flags = 0x8000;          out_uint16_le(s, seq);  /* unknown */
244          pdu->event[1].mouse_x = 15;          out_uint16_le(s, 0x32); /* entry size */
         pdu->event[1].mouse_y = 0;  
245    
246          pdu->event[2].event_time = now;          s_mark_end(s);
247          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;  
248  }  }
249    
250  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  /* Output general capability set */
251    static void
252    rdp_out_general_caps(STREAM s)
253  {  {
254          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_GENERAL);
255            out_uint16_le(s, RDP_CAPLEN_GENERAL);
256    
257          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          out_uint16_le(s, 1);    /* OS major type */
258          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          out_uint16_le(s, 3);    /* OS minor type */
259          res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;          out_uint16_le(s, 0x200);        /* Protocol version */
260            out_uint16(s, 0);       /* Pad */
261          return res;          out_uint16(s, 0);       /* Compression types */
262            out_uint16(s, 0);       /* Pad */
263            out_uint16(s, 0);       /* Update capability */
264            out_uint16(s, 0);       /* Remote unshare capability */
265            out_uint16(s, 0);       /* Compression level */
266            out_uint16(s, 0);       /* Pad */
267  }  }
268    
269  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)  /* Output bitmap capability set */
270    static void
271    rdp_out_bitmap_caps(STREAM s)
272  {  {
273          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_BITMAP);
274            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;  
275    
276          return res;          out_uint16_le(s, 8);    /* Preferred BPP */
277            out_uint16_le(s, 1);    /* Receive 1 BPP */
278            out_uint16_le(s, 1);    /* Receive 4 BPP */
279            out_uint16_le(s, 1);    /* Receive 8 BPP */
280            out_uint16_le(s, 800);  /* Desktop width */
281            out_uint16_le(s, 600);  /* Desktop height */
282            out_uint16(s, 0);       /* Pad */
283            out_uint16(s, 0);       /* Allow resize */
284            out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */
285            out_uint16(s, 0);       /* Unknown */
286            out_uint16_le(s, 1);    /* Unknown */
287            out_uint16(s, 0);       /* Pad */
288  }  }
289    
290  BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)  /* Output order capability set */
291    static void
292    rdp_out_order_caps(STREAM s)
293  {  {
294          uint8 change;          uint8 order_caps[32];
         BOOL res;  
295    
         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;  
296    
297          if (datasize > sizeof(colors->colors))          memset(order_caps, 0, 32);
298                  return False;          order_caps[0] = 1;      /* dest blt */
299            order_caps[1] = 1;      /* pat blt */
300            order_caps[2] = 1;      /* screen blt */
301            order_caps[3] = 1;      /* required for memblt? */
302            order_caps[8] = 1;      /* line */
303            order_caps[9] = 1;      /* line */
304            order_caps[10] = 1;     /* rect */
305            order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */
306            order_caps[13] = 1;     /* memblt */
307            order_caps[14] = 1;     /* triblt */
308            order_caps[22] = 1;     /* polyline */
309            order_caps[27] = 1;     /* text2 */
310            out_uint16_le(s, RDP_CAPSET_ORDER);
311            out_uint16_le(s, RDP_CAPLEN_ORDER);
312    
313          memcpy(colors->colors, s->data + s->offset, datasize);          out_uint8s(s, 20);      /* Terminal desc, pad */
314          s->offset += datasize;          out_uint16_le(s, 1);    /* Cache X granularity */
315          return True;          out_uint16_le(s, 20);   /* Cache Y granularity */
316            out_uint16(s, 0);       /* Pad */
317            out_uint16_le(s, 1);    /* Max order level */
318            out_uint16_le(s, 0x147);        /* Number of fonts */
319            out_uint16_le(s, 0x2a); /* Capability flags */
320            out_uint8p(s, order_caps, 32);  /* Orders supported */
321            out_uint16_le(s, 0x6a1);        /* Text capability flags */
322            out_uint8s(s, 6);       /* Pad */
323            out_uint32_le(s, desktop_save == False ? 0 : 0x38400);  /* Desktop cache size */
324            out_uint32(s, 0);       /* Unknown */
325            out_uint32_le(s, 0x4e4);        /* Unknown */
326  }  }
327    
328  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  /* Output bitmap cache capability set */
329    static void
330    rdp_out_bmpcache_caps(STREAM s)
331  {  {
332          uint16 length = RDP_CAPLEN_GENERAL;          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
333          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;  
         }  
334    
335          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          out_uint8s(s, 24);      /* unused */
336          res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;          out_uint16_le(s, 0x258);        /* entries */
337          res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;          out_uint16_le(s, 0x100);        /* max cell size */
338          res = res ? lsb_io_uint16(s, &caps->pad1          ) : False;          out_uint16_le(s, 0x12c);        /* entries */
339          res = res ? lsb_io_uint16(s, &caps->compress_types) : False;          out_uint16_le(s, 0x400);        /* max cell size */
340          res = res ? lsb_io_uint16(s, &caps->pad2          ) : False;          out_uint16_le(s, 0x106);        /* entries */
341          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;  
342  }  }
343    
344  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  /* Output control capability set */
345    static void
346    rdp_out_control_caps(STREAM s)
347  {  {
348          if (!lsb_io_uint16(s, &info->entries      ))          out_uint16_le(s, RDP_CAPSET_CONTROL);
349                  return False;          out_uint16_le(s, RDP_CAPLEN_CONTROL);
   
         if (!lsb_io_uint16(s, &info->max_cell_size))  
                 return False;  
350    
351          return True;          out_uint16(s, 0);       /* Control capabilities */
352            out_uint16(s, 0);       /* Remote detach */
353            out_uint16_le(s, 2);    /* Control interest */
354            out_uint16_le(s, 2);    /* Detach interest */
355  }  }
356    
357  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  /* Output activation capability set */
358    static void
359    rdp_out_activate_caps(STREAM s)
360  {  {
361          uint16 length = RDP_CAPLEN_BMPCACHE;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
362          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;  
363    
364          for (i = 0; i < 3; i++)          out_uint16(s, 0);       /* Help key */
365                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;          out_uint16(s, 0);       /* Help index key */
366            out_uint16(s, 0);       /* Extended help key */
367          return res;          out_uint16(s, 0);       /* Window activate */
368  }  }
369    
370  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  /* Output pointer capability set */
371    static void
372    rdp_out_pointer_caps(STREAM s)
373  {  {
374          uint16 length = RDP_CAPLEN_CONTROL;          out_uint16_le(s, RDP_CAPSET_POINTER);
375          uint16 pkt_length = length;          out_uint16_le(s, RDP_CAPLEN_POINTER);
         BOOL res;  
376    
377          res = lsb_io_uint16(s, &pkt_length);          out_uint16(s, 0);       /* Colour pointer */
378          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;  
379  }  }
380    
381  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  /* Output share capability set */
382    static void
383    rdp_out_share_caps(STREAM s)
384  {  {
385          uint16 length = RDP_CAPLEN_ACTIVATE;          out_uint16_le(s, RDP_CAPSET_SHARE);
386          uint16 pkt_length = length;          out_uint16_le(s, RDP_CAPLEN_SHARE);
         BOOL res;  
387    
388          res = lsb_io_uint16(s, &pkt_length);          out_uint16(s, 0);       /* userid */
389          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;  
390  }  }
391    
392  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  /* Output colour cache capability set */
393    static void
394    rdp_out_colcache_caps(STREAM s)
395  {  {
396          uint16 length = RDP_CAPLEN_POINTER;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
397          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;  
398    
399          return res;          out_uint16_le(s, 6);    /* cache size */
400            out_uint16(s, 0);       /* pad */
401  }  }
402    
403  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)  static uint8 canned_caps[] = {
404            0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
405            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
406            0x00, 0x00, 0x00, 0x00, 0x00,
407            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408            0x00, 0x00, 0x00, 0x00, 0x00,
409            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410            0x00, 0x00, 0x00, 0x00, 0x00,
411            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
412            0x00, 0x00, 0x00, 0x00, 0x00,
413            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414            0x0C, 0x00, 0x08, 0x00, 0x01,
415            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
416            0x10, 0x00, 0x34, 0x00, 0xFE,
417            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
418            0xFE, 0x00, 0x08, 0x00, 0xFE,
419            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
420            0xFE, 0x00, 0x80, 0x00, 0xFE,
421            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
422            0x02, 0x00, 0x00, 0x00
423    };
424    
425    /* Output unknown capability set */
426    static void
427    rdp_out_unknown_caps(STREAM s)
428    {
429            out_uint16_le(s, RDP_CAPSET_UNKNOWN);
430            out_uint16_le(s, 0x58);
431    
432            out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
433    }
434    
435    /* Send a confirm active PDU */
436    static void
437    rdp_send_confirm_active(void)
438    {
439            STREAM s;
440            uint16 caplen =
441                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
442                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
443                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
444                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
445    
446            s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));
447    
448            out_uint32_le(s, rdp_shareid);
449            out_uint16_le(s, 0x3ea);        /* userid */
450            out_uint16_le(s, sizeof(RDP_SOURCE));
451            out_uint16_le(s, caplen);
452    
453            out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
454            out_uint16_le(s, 0xd);  /* num_caps */
455            out_uint8s(s, 2);       /* pad */
456    
457            rdp_out_general_caps(s);
458            rdp_out_bitmap_caps(s);
459            rdp_out_order_caps(s);
460            rdp_out_bmpcache_caps(s);
461            rdp_out_colcache_caps(s);
462            rdp_out_activate_caps(s);
463            rdp_out_control_caps(s);
464            rdp_out_pointer_caps(s);
465            rdp_out_share_caps(s);
466            rdp_out_unknown_caps(s);
467    
468            s_mark_end(s);
469            rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);
470    }
471    
472    /* Respond to a demand active PDU */
473    static void
474    process_demand_active(STREAM s)
475  {  {
476          uint16 length = RDP_CAPLEN_SHARE;          uint8 type;
         uint16 pkt_length = length;  
         BOOL res;  
477    
478          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;  
         }  
479    
480          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;  
481    
482          return res;          rdp_send_confirm_active();
483  }          rdp_send_synchronise();
484            rdp_send_control(RDP_CTL_COOPERATE);
485            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
486            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
487            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
488            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
489            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
490            rdp_send_fonts(1);
491            rdp_send_fonts(2);
492            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
493            reset_order_state();
494    }
495    
496    /* Process a pointer PDU */
497    static void
498    process_pointer_pdu(STREAM s)
499    {
500            uint16 message_type;
501            uint16 x, y, width, height, cache_idx, masklen, datalen;
502            uint8 *mask, *data;
503            HCURSOR cursor;
504    
505  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)          in_uint16_le(s, message_type);
506  {          in_uint8s(s, 2);        /* pad */
         uint16 length = RDP_CAPLEN_COLCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
507    
508          res = lsb_io_uint16(s, &pkt_length);          switch (message_type)
         if (pkt_length != length)  
509          {          {
510                  fprintf(stderr, "Unrecognised capabilities size\n");                  case RDP_POINTER_MOVE:
511                  return False;                          in_uint16_le(s, x);
512          }                          in_uint16_le(s, y);
513                            if (s_check(s))
514          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;                                  ui_move_pointer(x, y);
515          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;                          break;
   
         return res;  
 }  
516    
517  uint8 canned_caps[] = {                  case RDP_POINTER_COLOR:
518  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,                          in_uint16_le(s, cache_idx);
519  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                          in_uint16_le(s, x);
520  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                          in_uint16_le(s, y);
521  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                          in_uint16_le(s, width);
522  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,                          in_uint16_le(s, height);
523  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x01,                          in_uint16_le(s, masklen);
524  0x00,0x00,0x00,0x0E,0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x34,0x00,0xFE,                          in_uint16_le(s, datalen);
525  0x00,0x04,0x00,0xFE,0x00,0x04,0x00,0xFE,0x00,0x08,0x00,0xFE,0x00,0x08,0x00,0xFE,                          in_uint8p(s, data, datalen);
526  0x00,0x10,0x00,0xFE,0x00,0x20,0x00,0xFE,0x00,0x40,0x00,0xFE,0x00,0x80,0x00,0xFE,                          in_uint8p(s, mask, masklen);
527  0x00,0x00,0x01,0x40,0x00,0x00,0x08,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00                          cursor = ui_create_cursor(x, y, width, height, mask, data);
528  };                          ui_set_cursor(cursor);
529                            cache_put_cursor(cache_idx, cursor);
530                            break;
531    
532  BOOL rdp_io_unknown_caps(STREAM s, void *caps)                  case RDP_POINTER_CACHED:
533  {                          in_uint16_le(s, cache_idx);
534          uint16 length = 0x58;                          ui_set_cursor(cache_get_cursor(cache_idx));
535          uint16 pkt_length = length;                          break;
         BOOL res;  
536    
537          res = lsb_io_uint16(s, &pkt_length);                  default:
538          if (pkt_length != length)                          DEBUG(("Pointer message 0x%x\n", message_type));
         {  
                 fprintf(stderr, "Unrecognised capabilities size\n");  
                 return False;  
539          }          }
   
         res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;  
   
         return res;  
540  }  }
541    
542  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  /* Process bitmap updates */
543    static void
544    process_bitmap_updates(STREAM s)
545  {  {
546          uint16 capset;          uint16 num_updates;
547          uint16 length;          uint16 left, top, right, bottom, width, height;
548          BOOL res;          uint16 cx, cy, bpp, compress, bufsize, size;
549            uint8 *data, *bmpdata;
550          int i;          int i;
551    
552          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;  
553    
554          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)  
555          {          {
556                  fprintf(stderr, "RDP source descriptor too long\n");                  in_uint16_le(s, left);
557                  return False;                  in_uint16_le(s, top);
558          }                  in_uint16_le(s, right);
559                    in_uint16_le(s, bottom);
560                    in_uint16_le(s, width);
561                    in_uint16_le(s, height);
562                    in_uint16_le(s, bpp);
563                    in_uint16_le(s, compress);
564                    in_uint16_le(s, bufsize);
565    
566          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;                  cx = right - left + 1;
567          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;  
568    
569                          if (!lsb_io_uint16(s, &capset))                  DEBUG(("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n",
570                                  return False;                         left, top, right, bottom, width, height, compress));
571    
572                          switch (capset)                  if (!compress)
573                    {
574                            int y;
575                            bmpdata = xmalloc(width * height);
576                            for (y = 0; y < height; y++)
577                          {                          {
578                          case RDP_CAPSET_GENERAL:                                  in_uint8a(s, &bmpdata[(height - y - 1) * width], width);
                                 res = rdp_io_general_caps (s, &pdu->general_caps );  
                                 break;  
                         case RDP_CAPSET_BITMAP:  
                                 res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );  
                                 break;  
                         case RDP_CAPSET_ORDER:  
                                 res = rdp_io_order_caps   (s, &pdu->order_caps   );  
                                 break;  
                         case RDP_CAPSET_BMPCACHE:  
                                 res = rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps);  
                                 break;  
                         case RDP_CAPSET_CONTROL:  
                                 res = rdp_io_control_caps (s, &pdu->control_caps );  
                                 break;  
                         case RDP_CAPSET_ACTIVATE:  
                                 res = rdp_io_activate_caps(s, &pdu->activate_caps);  
                                 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);  
579                          }                          }
580                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
581                            xfree(bmpdata);
582                            continue;
583                  }                  }
         }  
584    
585          return res;                  in_uint8s(s, 2);        /* pad */
586  }                  in_uint16_le(s, size);
587                    in_uint8s(s, 4);        /* line_size, final_size */
588                    in_uint8p(s, data, size);
589    
590  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)                  bmpdata = xmalloc(width * height);
591  {                  if (bitmap_decompress(bmpdata, width, height, data, size))
592          BOOL res = True;                  {
593                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
594          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;  
595    
596          return res;                  xfree(bmpdata);
597            }
598  }  }
599    
600  BOOL rdp_io_synchronize_pdu(STREAM s, RDP_SYNCHRONIZE_PDU *pdu)  /* Process a palette update */
601    static void
602    process_palette(STREAM s)
603  {  {
604          BOOL res = True;          HCOLOURMAP hmap;
605            COLOURMAP map;
606            uint8 *colours;
607    
608          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          in_uint8s(s, 2);        /* pad */
609          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          in_uint16_le(s, map.ncolours);
610            in_uint8s(s, 2);        /* pad */
611            in_uint8p(s, colours, (map.ncolours * 3));
612            map.colours = (COLOURENTRY *) colours;
613    
614          return res;          hmap = ui_create_colourmap(&map);
615            ui_set_colourmap(hmap);
616  }  }
617    
618  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  /* Process an update PDU */
619    static void
620    process_update_pdu(STREAM s)
621  {  {
622          BOOL res = True;          uint16 update_type;
623    
624          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;  
625    
626          if (!res)          switch (update_type)
                 return False;  
   
         switch (evt->message_type)  
627          {          {
628          case RDP_INPUT_CODEPOINT:                  case RDP_UPDATE_ORDERS:
629          case RDP_INPUT_VIRTKEY:                          process_orders(s);
630                  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;  
 }  
631    
632  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)                  case RDP_UPDATE_BITMAP:
633  {                          process_bitmap_updates(s);
634          BOOL res = True;                          break;
         int i;  
635    
636          res = res ? lsb_io_uint16(s, &pdu->num_events) : False;                  case RDP_UPDATE_PALETTE:
637          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;                          process_palette(s);
638                            break;
639    
640          if (pdu->num_events > RDP_MAX_EVENTS)                  case RDP_UPDATE_SYNCHRONIZE:
641          {                          break;
                 fprintf(stderr, "Too many events in one PDU\n");  
                 return False;  
         }  
642    
643          for (i = 0; i < pdu->num_events; i++)                  default:
644          {                          unimpl("update %d\n", update_type);
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
645          }          }
646    
         return res;  
647  }  }
648    
649  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  /* Process data PDU */
650    static void
651    process_data_pdu(STREAM s)
652  {  {
653          BOOL res = True;          uint8 data_pdu_type;
654    
655          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
656          res = res ? lsb_io_uint16(s, &font->flags    ) : False;          in_uint8(s, data_pdu_type);
657          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;  
658    
659          return res;          switch (data_pdu_type)
660  }          {
661                    case RDP_DATA_PDU_UPDATE:
662                            process_update_pdu(s);
663                            break;
664    
665  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)                  case RDP_DATA_PDU_POINTER:
666  {                          process_pointer_pdu(s);
667          BOOL res = True;                          break;
         int i;  
668    
669          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;                  case RDP_DATA_PDU_BELL:
670          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;                          ui_bell();
671          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;                          break;
         res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  
672    
673          if (pdu->num_fonts > RDP_MAX_FONTS)                  case RDP_DATA_PDU_LOGON:
674          {                          /* User logged on */
675                  fprintf(stderr, "Too many fonts in one PDU\n");                          break;
                 return False;  
         }  
676    
677          for (i = 0; i < pdu->num_fonts; i++)                  default:
678          {                          unimpl("data PDU %d\n", data_pdu_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
679          }          }
   
         return res;  
680  }  }
681    
682  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  /* Process incoming packets */
683    void
684    rdp_main_loop(void)
685  {  {
686          BOOL res = True;          uint8 type;
687            STREAM s;
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
688    
689          return res;          while ((s = rdp_recv(&type)) != NULL)
690  }          {
691                    switch (type)
692                    {
693                            case RDP_PDU_DEMAND_ACTIVE:
694                                    process_demand_active(s);
695                                    break;
696    
697  BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)                          case RDP_PDU_DEACTIVATE:
698  {                                  break;
         BOOL res = True;  
699    
700          res = res ? lsb_io_uint16(s, &rso->length) : False;                          case RDP_PDU_DATA:
701          res = res ? lsb_io_uint16(s, &rso->flags ) : False;                                  process_data_pdu(s);
702          res = res ? prs_io_uint8 (s, &rso->type  ) : False;                                  break;
703    
704          return res;                          default:
705                                    unimpl("PDU %d\n", type);
706                    }
707            }
708  }  }
709    
710  BOOL rdp_io_bitmap_header(STREAM s, RDP_BITMAP_HEADER *rdh)  /* Establish a connection up to the RDP layer */
711    BOOL
712    rdp_connect(char *server, uint32 flags, char *domain, char *password,
713                char *command, char *directory)
714  {  {
715          BOOL res = True;          if (!sec_connect(server))
716                    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;  
717    
718          return res;          rdp_send_logon_info(flags, domain, username, password, command, directory);
719            return True;
720  }  }
721    
722  BOOL rdp_io_pointer(STREAM s, RDP_POINTER *ptr)  /* Disconnect from the RDP layer */
723    void
724    rdp_disconnect(void)
725  {  {
726          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;  
727  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26