/[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 9 by matty, Tue Jul 25 12:34:29 2000 UTC revision 28 by matty, Wed Jun 20 13:54:48 2001 UTC
# 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, int width, int height)  extern char username[16];
25  {  extern BOOL bitmap_compression;
26          HCONN conn;  extern BOOL orders;
27    extern BOOL use_encryption;
28          if ((conn = mcs_connect(server)) == NULL)  extern BOOL desktop_save;
                 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);  
   
         return conn;  
   
 }  
   
 /* 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  
 };  
   
 uint8 precanned_key_packet_e1[] = {  
 0x01,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x7c,0xbd,0x8b,0x8f,0x16,0x2b,0xa1,0x00,  
 0xc6,0xfb,0x8a,0x39,0xf5,0x33,0xed,0x36,0x14,0x55,0x17,0x8c,0x3a,0xde,0x5e,0xdf,  
 0xcb,0x41,0x4c,0xc7,0x89,0x7d,0xe3,0xe9,0x34,0x08,0xda,0xdc,0x08,0x77,0x98,0xda,  
 0x65,0xae,0x27,0x74,0xf1,0x79,0xd0,0x28,0x54,0x64,0x86,0x7f,0x02,0xe0,0x71,0x51,  
 0x56,0x4e,0xca,0x72,0x94,0x62,0x49,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00  
 };  
   
 uint8 precanned_key_packet_e2[] = {  
 0x48,0x00,0x00,0x00,0x8a,0xe4,0x9f,0x8a,0xd5,0x04,0x02,0xfd,0x09,0x1f,0xff,0x53,  
 0xe0,0xb2,0x72,0x8b,0x19,0xba,0x22,0xe4,0x2a,0x7b,0xeb,0x79,0xa8,0x83,0x31,0x6f,  
 0x5c,0xcc,0x37,0x9c,0xe8,0x73,0x64,0x64,0xd3,0xab,0xaa,0x9f,0xbe,0x49,0x27,0xfc,  
 0x95,0xf3,0x6e,0xf8,0xb1,0x01,0x7c,0xba,0xa9,0xc5,0x35,0x9c,0x8f,0x74,0x3a,0x9f,  
 0xd4,0x26,0x4d,0x39,0x90,0xbe,0xf4,0xfb,0x72,0x9e,0x54,0x18  
 };  
   
 /* 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);  
 }  
   
 /* Create an RC4 key and transfer it to the server */  
 void rdp_establish_key_e1(HCONN conn)  
 {  
         mcs_init_data(conn);  
         memcpy(conn->out.data + conn->out.offset, precanned_key_packet_e1,  
                sizeof(precanned_key_packet_e1));  
         conn->out.offset += sizeof(precanned_key_packet_e1);  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 /* Create an RC4 key and transfer it to the server */  
 void rdp_establish_key_e2(HCONN conn)  
 {  
         mcs_init_data(conn);  
         memcpy(conn->out.data + conn->out.offset, precanned_key_packet_e2,  
                sizeof(precanned_key_packet_e2));  
         conn->out.offset += sizeof(precanned_key_packet_e2);  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 /* Horrible horrible certificate stuff. Work out later. */  
 uint8 precanned_cert_packet[] = { // 4c8  
 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;  
   
         POP_LAYER(conn->out, rdp_offset);  
         length = conn->out.end - conn->out.offset;  
         rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);  
         rdp_io_header(&conn->out, &hdr);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 /* Initialise RDP transport data packet */  
 void rdp_init_data(HCONN conn)  
 {  
         mcs_init_data(conn);  
         PUSH_LAYER(conn->out, rdp_offset, 18);  
 }  
   
 /* Transmit RDP transport data packet */  
 void rdp_send_data(HCONN conn, uint16 data_pdu_type)  
 {  
         RDP_HEADER hdr;  
         RDP_DATA_HEADER datahdr;  
         int length = conn->out.end - conn->out.offset;  
   
         POP_LAYER(conn->out, rdp_offset);  
         length = conn->out.end - conn->out.offset;  
         rdp_make_header(&hdr, length, RDP_PDU_DATA, conn->mcs_userid);  
         rdp_io_header(&conn->out, &hdr);  
         rdp_make_data_header(&datahdr, 0x103ea, length, data_pdu_type);  
         rdp_io_data_header(&conn->out, &datahdr);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 void rdp_send_confirm_active(HCONN conn, uint32 shareid, int width, int height)  
 {  
         RDP_ACTIVE_PDU active;  
   
         rdp_init(conn);  
         rdp_make_active_pdu(&active, shareid, conn->mcs_userid, width, height);  
         rdp_io_active_pdu(&conn->out, &active, RDP_PDU_CONFIRM_ACTIVE);  
         MARK_END(conn->out);  
         rdp_send(conn, RDP_PDU_CONFIRM_ACTIVE);  
 }  
   
 void rdp_send_synchronize(HCONN conn)  
 {  
         RDP_SYNCHRONISE_PDU sync;  
   
         rdp_init_data(conn);  
         rdp_make_synchronise_pdu(&sync, 1002);  
         rdp_io_synchronise_pdu(&conn->out, &sync);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_SYNCHRONIZE);  
 }  
   
 void rdp_send_control(HCONN conn, uint16 action)  
 {  
         RDP_CONTROL_PDU control;  
   
         rdp_init_data(conn);  
         rdp_make_control_pdu(&control, action);  
         rdp_io_control_pdu(&conn->out, &control);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_CONTROL);  
 }  
   
 void rdp_send_fonts(HCONN conn, uint16 seqno)  
 {  
         RDP_FONT_PDU fonts;  
   
         rdp_init_data(conn);  
         rdp_make_font_pdu(&fonts, seqno);  
         rdp_io_font_pdu(&conn->out, &fonts);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_FONT2);  
 }  
   
 void rdp_send_input(HCONN conn, uint16 message_type, uint16 device_flags,  
                                 uint16 param1, uint16 param2)  
 {  
         RDP_INPUT_PDU input;  
   
         rdp_init_data(conn);  
         rdp_make_input_pdu(&input, message_type, device_flags, param1, param2);  
         rdp_io_input_pdu(&conn->out, &input);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_INPUT);  
 }  
   
 BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  
 {  
         RDP_HEADER hdr;  
   
         conn->in.offset = conn->in.rdp_offset;  
   
         if (conn->in.offset >= conn->in.end)  
         {  
                 if (!mcs_recv(conn, False))  
                         return False;  
         }  
   
         if (!rdp_io_header(&conn->in, &hdr))  
                 return False;  
   
         conn->in.rdp_offset += hdr.length;  
         *type = hdr.pdu_type & 0xf;  
   
 #if DUMP  
         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;  
 }  
29    
30  /* Disconnect from the RDP layer */  uint8 *next_packet;
31  void rdp_disconnect(HCONN conn)  uint32 rdp_shareid;
 {  
         mcs_disconnect(conn);  
 }  
   
 /* Construct an RDP header */  
 void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,  
                      uint16 userid)  
 {  
         hdr->length = length;  
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
 }  
32    
33  /* Parse an RDP header */  /* Initialise an RDP packet */
34  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  static STREAM
35    rdp_init(int maxlen)
36  {  {
37          BOOL res = True;          STREAM s;
38    
39          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          s = sec_init(use_encryption ? SEC_ENCRYPT : 0, maxlen + 6);
40          res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;          s_push_layer(s, rdp_hdr, 6);
         if ((hdr->pdu_type & 0xf) != RDP_PDU_DEACTIVATE)  
                 res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;  
41    
42          return res;          return s;
43  }  }
44    
45  /* Construct a data header */  /* Send an RDP packet */
46  void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,  static void
47                            uint16 length, uint16 data_pdu_type)  rdp_send(STREAM s, uint8 pdu_type)
48  {  {
49          hdr->shareid = shareid;          uint16 length;
         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;  
 }  
50    
51  /* Parse a data header */          s_pop_layer(s, rdp_hdr);
52  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)          length = s->end - s->p;
 {  
         BOOL res = True;  
53    
54          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;          out_uint16_le(s, length);
55          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;          out_uint16_le(s, (pdu_type | 0x10));    /* Version 1 */
56          res = res ? prs_io_uint8 (s, &hdr->streamid     ) : False;          out_uint16_le(s, (mcs_userid + 1001));
         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;  
57    
58          return res;          sec_send(s, use_encryption ? SEC_ENCRYPT : 0);
59  }  }
60    
61  BOOL rdp_io_present(STREAM s, uint32 *present, uint8 flags, int size)  /* Receive an RDP packet */
62    static STREAM
63    rdp_recv(uint8 *type)
64  {  {
65          uint8 bits;          static STREAM rdp_s;
66          int i;          uint16 length, pdu_type;
   
         if (flags & RDP_ORDER_SMALL)  
         {  
                 size--;  
         }  
   
         if (flags & RDP_ORDER_TINY)  
         {  
                 if (size < 2)  
                         return False;  
67    
68                  size -= 2;          if ((rdp_s == NULL) || (next_packet >= rdp_s->end))
         }  
   
         *present = 0;  
         for (i = 0; i < size; i++)  
69          {          {
70                  prs_io_uint8(s, &bits);                  rdp_s = sec_recv();
71                  *present |= bits << (i * 8);                  if (rdp_s == NULL)
72          }                          return NULL;
73    
74          return True;                  next_packet = rdp_s->p;
 }  
   
 BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)  
 {  
         uint8 change;  
         BOOL res;  
   
         if (delta)  
         {  
                 res = prs_io_uint8(s, &change);  
                 *coord += (char)change;  
75          }          }
76          else          else
77          {          {
78                  res = lsb_io_uint16(s, coord);                  rdp_s->p = next_packet;
79          }          }
80    
81          return res;          in_uint16_le(rdp_s, length);
82  }          in_uint16_le(rdp_s, pdu_type);
83            in_uint8s(rdp_s, 2);    /* userid */
84  BOOL rdp_io_colour(STREAM s, uint8 *colour)          *type = pdu_type & 0xf;
 {  
         BOOL res;  
   
         res = prs_io_uint8(s, colour);  
         s->offset += 2;  
   
         return res;  
 }  
   
 BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours)  
 {  
         int datasize;  
   
         lsb_io_uint16(s, &colours->ncolours);  
         datasize = colours->ncolours * 3;  
   
         if (datasize > sizeof(colours->colours))  
                 return False;  
   
         memcpy(colours->colours, s->data + s->offset, datasize);  
         s->offset += datasize;  
         return True;  
 }  
   
 BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds)  
 {  
         uint8 present;  
   
         prs_io_uint8(s, &present);  
   
         if (present & 1)  
                 rdp_io_coord(s, &bounds->left, False);  
         else if (present & 16)  
                 rdp_io_coord(s, &bounds->left, True);  
   
         if (present & 2)  
                 rdp_io_coord(s, &bounds->top, False);  
         else if (present & 32)  
                 rdp_io_coord(s, &bounds->top, True);  
   
         if (present & 4)  
                 rdp_io_coord(s, &bounds->right, False);  
         else if (present & 64)  
                 rdp_io_coord(s, &bounds->right, True);  
   
         if (present & 8)  
                 rdp_io_coord(s, &bounds->bottom, False);  
         else if (present & 128)  
                 rdp_io_coord(s, &bounds->bottom, True);  
   
         return True;  
 }  
   
 BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present)  
 {  
         BOOL res = True;  
   
         if (present & 1)  
                 res = res ? prs_io_uint8(s, &pen->style) : False;  
   
         if (present & 2)  
                 res = res ? prs_io_uint8(s, &pen->width) : False;  
   
         if (present & 4)  
                 res = res ? rdp_io_colour(s, &pen->colour) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_brush(STREAM s, BRUSH *brush, uint32 present)  
 {  
         BOOL res = True;  
   
         if (present & 1)  
                 res = res ? prs_io_uint8(s, &brush->xorigin) : False;  
   
         if (present & 2)  
                 res = res ? prs_io_uint8(s, &brush->yorigin) : False;  
   
         if (present & 4)  
                 res = res ? prs_io_uint8(s, &brush->style) : False;  
85    
86          if (present & 8)  #if RDP_DEBUG
87                  res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;          DEBUG("RDP packet (type %x):\n", *type);
88            hexdump(next_packet, length);
89    #endif /*  */
90    
91          if (present & 16)          next_packet += length;
92                  res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;          return rdp_s;
   
         return res;  
93  }  }
94    
95  /* Construct a confirm/demand active PDU */  /* Initialise an RDP data packet */
96  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid,  static STREAM
97                                  int width, int height)  rdp_init_data(int maxlen)
98  {  {
99          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));  
100    
101          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          s = sec_init(use_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
102                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          s_push_layer(s, rdp_hdr, 18);
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
103    
104          rdp_make_general_caps (&pdu->general_caps );          return s;
         rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);  
         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);  
105  }  }
106    
107  /* Parse a confirm/demand active PDU */  /* Send an RDP data packet */
108  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  static void
109    rdp_send_data(STREAM s, uint8 data_pdu_type)
110  {  {
         uint16 capset;  
111          uint16 length;          uint16 length;
         BOOL res;  
         int i;  
   
         res = lsb_io_uint32(s, &pdu->shareid);  
   
         if (pdutype == RDP_PDU_CONFIRM_ACTIVE)  
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
   
         res = res ? lsb_io_uint16(s, &pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
   
         if (pdu->source_len > 48)  
         {  
                 ERROR("RDP source descriptor too long\n");  
                 return False;  
         }  
   
         res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
   
         if (s->marshall)  
         {  
                 capset = RDP_CAPSET_GENERAL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_general_caps(s, &pdu->general_caps) : False;  
   
                 capset = RDP_CAPSET_BITMAP;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bitmap_caps (s, &pdu->bitmap_caps ) : False;  
   
                 capset = RDP_CAPSET_ORDER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_order_caps  (s, &pdu->order_caps  ) : False;  
   
                 capset = RDP_CAPSET_BMPCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps) : False;  
   
                 capset = RDP_CAPSET_COLCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_colcache_caps(s, &pdu->colcache_caps) : False;  
   
                 capset = RDP_CAPSET_ACTIVATE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_activate_caps(s, &pdu->activate_caps) : False;  
   
                 capset = RDP_CAPSET_CONTROL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_control_caps(s, &pdu->control_caps) : False;  
   
                 capset = RDP_CAPSET_POINTER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_pointer_caps(s, &pdu->pointer_caps) : False;  
   
                 capset = RDP_CAPSET_SHARE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_share_caps  (s, &pdu->share_caps  ) : False;  
   
                 capset = RDP_CAPSET_UNKNOWN;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_unknown_caps(s, NULL) : False;  
         }  
         else  
         {  
                 for (i = 0; i < pdu->num_caps; i++)  
                 {  
                         if (!res)  
                                 return False;  
   
                         if (!lsb_io_uint16(s, &capset))  
                                 return False;  
   
                         switch (capset)  
                         {  
                         case RDP_CAPSET_GENERAL:  
                                 res = rdp_io_general_caps (s, &pdu->general_caps );  
                                 break;  
                         case RDP_CAPSET_BITMAP:  
                                 res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );  
                                 break;  
                         case RDP_CAPSET_ORDER:  
                                 res = rdp_io_order_caps   (s, &pdu->order_caps   );  
                                 break;  
                         case RDP_CAPSET_BMPCACHE:  
                                 res = rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps);  
                                 break;  
                         case RDP_CAPSET_CONTROL:  
                                 res = rdp_io_control_caps (s, &pdu->control_caps );  
                                 break;  
                         case RDP_CAPSET_ACTIVATE:  
                                 res = rdp_io_activate_caps(s, &pdu->activate_caps);  
                                 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:  
                                 NOTIMP("capset 0x%x\n", capset);  
   
                                 if (!lsb_io_uint16(s, &length))  
                                         return False;  
   
                                 s->offset += (length - 4);  
                         }  
                 }  
         }  
   
         return res;  
 }  
   
 /* Construct a control PDU */  
 void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  
 {  
         pdu->action = action;  
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
   
 /* Parse a control PDU */  
 BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  
 {  
         BOOL res = True;  
112    
113          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;          s_pop_layer(s, rdp_hdr);
114          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;          length = s->end - s->p;
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
115    
116          return res;          out_uint16_le(s, length);
117  }          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
118            out_uint16_le(s, (mcs_userid + 1001));
 /* Construct a synchronisation PDU */  
 void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  
 {  
         pdu->type = 1;  
         pdu->userid = userid;  
 }  
   
 /* Parse a synchronisation PDU */  
 BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)  
 {  
         BOOL res = True;  
119    
120          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          out_uint32_le(s, rdp_shareid);
121          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          out_uint8(s, 0);        /* pad */
122            out_uint8(s, 1);        /* streamid */
123            out_uint16(s, (length - 14));
124            out_uint8(s, data_pdu_type);
125            out_uint8(s, 0);        /* compress_type */
126            out_uint16(s, 0);       /* compress_len */
127    
128          return res;          sec_send(s, use_encryption ? SEC_ENCRYPT : 0);
129  }  }
130    
131  /* Parse a single input event */  /* Output a string in Unicode */
132  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  void
133    rdp_out_unistr(STREAM s, char *string, int len)
134  {  {
135          BOOL res = True;          int i = 0, j = 0;
136    
137          res = res ? lsb_io_uint32(s, &evt->event_time)   : False;          len += 2;
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
         res = res ? lsb_io_uint16(s, &evt->device_flags) : False;  
138    
139          if (!res)          while (i < len)
                 return False;  
   
         switch (evt->message_type)  
140          {          {
141          case RDP_INPUT_CODEPOINT:                  s->p[i++] = string[j++];
142          case RDP_INPUT_VIRTKEY:                  s->p[i++] = 0;
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 break;  
         case RDP_INPUT_SYNCHRONIZE:  
         case RDP_INPUT_SCANCODE:  
         case RDP_INPUT_MOUSE:  
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 res = res ? lsb_io_uint16(s, &evt->param2) : False;  
                 break;  
         default:  
                 NOTIMP("input type %d\n", evt->message_type);  
                 return False;  
143          }          }
144    
145          return res;          s->p += len;
 }  
   
 /* Construct an input PDU */  
 void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  
                         uint16 device_flags, uint16 param1, uint16 param2)  
 {  
         uint32 now = time(NULL);  
   
         pdu->num_events = 1;  
         pdu->pad = 0;  
   
         pdu->event[0].event_time = now;  
         pdu->event[0].message_type = message_type;  
         pdu->event[0].device_flags = device_flags;  
         pdu->event[0].param1 = param1;  
         pdu->event[0].param2 = param2;  
146  }  }
147    
148  /* Parse an input PDU */  /* Parse a logon info packet */
149  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
150    rdp_send_logon_info(uint32 flags, char *domain, char *user,
151                        char *password, char *program, char *directory)
152  {  {
153          BOOL res = True;          int len_domain = 2 * strlen(domain);
154          int i;          int len_user = 2 * strlen(user);
155            int len_password = 2 * strlen(password);
156            int len_program = 2 * strlen(program);
157            int len_directory = 2 * strlen(directory);
158            uint32 sec_flags = use_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT)
159                                    : SEC_LOGON_INFO;
160            STREAM s;
161    
162          res = res ? lsb_io_uint16(s, &pdu->num_events) : False;          s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
163          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;                       + len_program + len_directory + 10);
   
         if (pdu->num_events > RDP_MAX_EVENTS)  
         {  
                 ERROR("Too many events in one PDU\n");  
                 return False;  
         }  
164    
165          for (i = 0; i < pdu->num_events; i++)          out_uint32(s, 0);
166          {          out_uint32_le(s, flags);
167                  res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;          out_uint16_le(s, len_domain);
168          }          out_uint16_le(s, len_user);
169            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          return res;          s_mark_end(s);
179            sec_send(s, sec_flags);
180  }  }
181    
182  /* Construct a font information PDU */  /* Send a control PDU */
183  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)  static void
184    rdp_send_control(uint16 action)
185  {  {
186          pdu->num_fonts = 0;          STREAM s;
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
 }  
187    
188  /* Parse a font information structure */          s = rdp_init_data(8);
 BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  
 {  
         BOOL res = True;  
189    
190          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;          out_uint16_le(s, action);
191          res = res ? lsb_io_uint16(s, &font->flags    ) : False;          out_uint16(s, 0);       /* userid */
192          res = res ? lsb_io_uint16(s, &font->width    ) : False;          out_uint32(s, 0);       /* control id */
         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;  
193    
194          return res;          s_mark_end(s);
195            rdp_send_data(s, RDP_DATA_PDU_CONTROL);
196  }  }
197    
198  /* Parse a font information PDU */  /* Send a synchronisation PDU */
199  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  static void
200    rdp_send_synchronise()
201  {  {
202          BOOL res = True;          STREAM s;
         int i;  
203    
204          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;          s = rdp_init_data(4);
         res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  
205    
206          if (pdu->num_fonts > RDP_MAX_FONTS)          out_uint16_le(s, 1);    /* type */
207          {          out_uint16_le(s, 1002);
                 ERROR("Too many fonts in one PDU\n");  
                 return False;  
         }  
   
         for (i = 0; i < pdu->num_fonts; i++)  
         {  
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
         }  
208    
209          return res;          s_mark_end(s);
210            rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
211  }  }
212    
213  /* Parse a pointer PDU */  /* Send a single input event */
214  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  void
215    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags,
216                   uint16 param1, uint16 param2)
217  {  {
218          BOOL res = True;          STREAM s;
219    
220          res = res ? lsb_io_uint16(s, &ptr->message) : False;          s = rdp_init_data(16);
         res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;  
221    
222          switch (ptr->message)          out_uint16_le(s, 1);    /* number of events */
223          {          out_uint16(s, 0);       /* pad */
                 case RDP_POINTER_MOVE:  
                         res = res ? lsb_io_uint16(s, &ptr->x      ) : False;  
                         res = res ? lsb_io_uint16(s, &ptr->y      ) : False;  
                         break;  
         }  
   
         return res;  
 }  
224    
225  /* Parse an update PDU */          out_uint32_le(s, time);
226  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)          out_uint16_le(s, message_type);
227  {          out_uint16_le(s, device_flags);
228          BOOL res = True;          out_uint16_le(s, param1);
229            out_uint16_le(s, param2);
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
230    
231          return res;          s_mark_end(s);
232            rdp_send_data(s, RDP_DATA_PDU_INPUT);
233  }  }
234    
235    /* Send an (empty) font information PDU */
236  /* PRIMARY ORDERS */  static void
237    rdp_send_fonts(uint16 seq)
 /* Parse an destination blt order */  
 BOOL rdp_io_destblt_order(STREAM s, DESTBLT_ORDER *os, uint32 present, BOOL delta)  
238  {  {
239          if (present & 0x01)          STREAM s;
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x02)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->cx, delta);  
240    
241          if (present & 0x08)          s = rdp_init_data(8);
                 rdp_io_coord(s, &os->cy, delta);  
242    
243          if (present & 0x10)          out_uint16(s, 0);       /* number of fonts */
244                  prs_io_uint8(s, &os->opcode);          out_uint16_le(s, 0x3e); /* unknown */
245            out_uint16_le(s, seq);  /* unknown */
246            out_uint16_le(s, 0x32); /* entry size */
247    
248          return PRS_ERROR(s);          s_mark_end(s);
249            rdp_send_data(s, RDP_DATA_PDU_FONT2);
250  }  }
251    
252  /* Parse an pattern blt order */  /* Output general capability set */
253  BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  static void
254    rdp_out_general_caps(STREAM s)
255  {  {
256          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_GENERAL);
257                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_GENERAL);
258    
259          if (present & 0x0002)          out_uint16_le(s, 1);    /* OS major type */
260                  rdp_io_coord(s, &os->y, delta);          out_uint16_le(s, 3);    /* OS minor type */
261            out_uint16_le(s, 0x200);        /* Protocol version */
262          if (present & 0x0004)          out_uint16(s, 0);       /* Pad */
263                  rdp_io_coord(s, &os->cx, delta);          out_uint16(s, 0);       /* Compression types */
264            out_uint16(s, 0);       /* Pad */
265          if (present & 0x0008)          out_uint16(s, 0);       /* Update capability */
266                  rdp_io_coord(s, &os->cy, delta);          out_uint16(s, 0);       /* Remote unshare capability */
267            out_uint16(s, 0);       /* Compression level */
268          if (present & 0x0010)          out_uint16(s, 0);       /* Pad */
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x0040)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         rdp_io_brush(s, &os->brush, present >> 7);  
   
         return PRS_ERROR(s);  
269  }  }
270    
271  /* Parse an screen blt order */  /* Output bitmap capability set */
272  BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  static void
273    rdp_out_bitmap_caps(STREAM s)
274  {  {
275          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_BITMAP);
276                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x0010)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0020)  
                 rdp_io_coord(s, &os->srcx, delta);  
277    
278          if (present & 0x0040)          out_uint16_le(s, 8);    /* Preferred BPP */
279                  rdp_io_coord(s, &os->srcy, delta);          out_uint16(s, 1);       /* Receive 1 BPP */
280            out_uint16(s, 1);       /* Receive 4 BPP */
281          return PRS_ERROR(s);          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  /* Parse a line order */  /* Output order capability set */
293  BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  static void
294    rdp_out_order_caps(STREAM s)
295  {  {
296          if (present & 0x0001)          uint8 order_caps[32];
                 lsb_io_uint16(s, &os->mixmode);  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->startx, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->starty, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->endx, delta);  
   
         if (present & 0x0010)  
                 rdp_io_coord(s, &os->endy, delta);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
297    
         if (present & 0x0040)  
                 prs_io_uint8(s, &os->opcode);  
298    
299          rdp_io_pen(s, &os->pen, present >> 7);          memset(order_caps, 0, 32);
300            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          return PRS_ERROR(s);          out_uint8s(s, 20);      /* Terminal desc, pad */
315            out_uint16_le(s, 1);    /* Cache X granularity */
316            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  /* Parse an opaque rectangle order */  /* Output bitmap cache capability set */
330  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  static void
331    rdp_out_bmpcache_caps(STREAM s)
332  {  {
333          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
334                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
335    
336          if (present & 0x02)          out_uint8s(s, 24);      /* unused */
337                  rdp_io_coord(s, &os->y, delta);          out_uint16_le(s, 0x258);        /* entries */
338            out_uint16_le(s, 0x100);        /* max cell size */
339          if (present & 0x04)          out_uint16_le(s, 0x12c);        /* entries */
340                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 0x400);        /* max cell size */
341            out_uint16_le(s, 0x106);        /* entries */
342          if (present & 0x08)          out_uint16_le(s, 0x1000);       /* max cell size */
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x10)  
                 prs_io_uint8(s, &os->colour);  
   
         return PRS_ERROR(s);  
343  }  }
344    
345  /* Parse a desktop save order */  /* Output control capability set */
346  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  static void
347    rdp_out_control_caps(STREAM s)
348  {  {
349          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_CONTROL);
350                  lsb_io_uint32(s, &os->offset);          out_uint16_le(s, RDP_CAPLEN_CONTROL);
   
         if (present & 0x02)  
                 rdp_io_coord(s, &os->left, delta);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->top, delta);  
351    
352          if (present & 0x08)          out_uint16(s, 0);       /* Control capabilities */
353                  rdp_io_coord(s, &os->right, delta);          out_uint16(s, 0);       /* Remote detach */
354            out_uint16_le(s, 2);    /* Control interest */
355          if (present & 0x10)          out_uint16_le(s, 2);    /* Detach interest */
                 rdp_io_coord(s, &os->bottom, delta);  
   
         if (present & 0x20)  
                 prs_io_uint8(s, &os->action);  
   
         return PRS_ERROR(s);  
356  }  }
357    
358  /* Parse a memory blt order */  /* Output activation capability set */
359  BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  static void
360    rdp_out_activate_caps(STREAM s)
361  {  {
362          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
363          {          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
                 prs_io_uint8(s, &os->cache_id);  
                 prs_io_uint8(s, &os->colour_table);  
         }  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x0010)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x0020)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0040)  
                 rdp_io_coord(s, &os->srcx, delta);  
   
         if (present & 0x0080)  
                 rdp_io_coord(s, &os->srcy, delta);  
364    
365          if (present & 0x0100)          out_uint16(s, 0);       /* Help key */
366                  lsb_io_uint16(s, &os->cache_idx);          out_uint16(s, 0);       /* Help index key */
367            out_uint16(s, 0);       /* Extended help key */
368          return PRS_ERROR(s);          out_uint16(s, 0);       /* Window activate */
369  }  }
370    
371  /* Parse a 3-way blt order */  /* Output pointer capability set */
372  BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta)  static void
373    rdp_out_pointer_caps(STREAM s)
374  {  {
375          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_POINTER);
376          {          out_uint16_le(s, RDP_CAPLEN_POINTER);
                 prs_io_uint8(s, &os->cache_id);  
                 prs_io_uint8(s, &os->colour_table);  
         }  
   
         if (present & 0x000002)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x000004)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x000008)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x000010)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x000020)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x000040)  
                 rdp_io_coord(s, &os->srcx, delta);  
   
         if (present & 0x000080)  
                 rdp_io_coord(s, &os->srcy, delta);  
   
         if (present & 0x000100)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x000200)  
                 rdp_io_colour(s, &os->fgcolour);  
377    
378          rdp_io_brush(s, &os->brush, present >> 10);          out_uint16(s, 0);       /* Colour pointer */
379            out_uint16_le(s, 20);   /* Cache size */
         if (present & 0x008000)  
                 lsb_io_uint16(s, &os->cache_idx);  
   
         if (present & 0x010000)  
                 lsb_io_uint16(s, &os->unknown);  
   
         return PRS_ERROR(s);  
380  }  }
381    
382  /* Parse a text order */  /* Output share capability set */
383  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  static void
384    rdp_out_share_caps(STREAM s)
385  {  {
386          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_SHARE);
387                  prs_io_uint8(s, &os->font);          out_uint16_le(s, RDP_CAPLEN_SHARE);
   
         if (present & 0x000002)  
                 prs_io_uint8(s, &os->flags);  
   
         if (present & 0x000004)  
                 prs_io_uint8(s, &os->unknown);  
   
         if (present & 0x000008)  
                 prs_io_uint8(s, &os->mixmode);  
   
         if (present & 0x000010)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         if (present & 0x000020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x000040)  
                 lsb_io_uint16(s, &os->clipleft);  
   
         if (present & 0x000080)  
                 lsb_io_uint16(s, &os->cliptop);  
   
         if (present & 0x000100)  
                 lsb_io_uint16(s, &os->clipright);  
   
         if (present & 0x000200)  
                 lsb_io_uint16(s, &os->clipbottom);  
388    
389          if (present & 0x000400)          out_uint16(s, 0);       /* userid */
390                  lsb_io_uint16(s, &os->boxleft);          out_uint16(s, 0);       /* pad */
   
         if (present & 0x000800)  
                 lsb_io_uint16(s, &os->boxtop);  
   
         if (present & 0x001000)  
                 lsb_io_uint16(s, &os->boxright);  
   
         if (present & 0x002000)  
                 lsb_io_uint16(s, &os->boxbottom);  
   
         if (present & 0x080000)  
                 lsb_io_uint16(s, &os->x);  
   
         if (present & 0x100000)  
                 lsb_io_uint16(s, &os->y);  
   
         if (present & 0x200000)  
         {  
                 prs_io_uint8(s, &os->length);  
                 prs_io_uint8s(s, os->text, os->length);  
         }  
   
         return PRS_ERROR(s);  
391  }  }
392    
393    /* Output colour cache capability set */
394  /* SECONDARY ORDERS */  static void
395    rdp_out_colcache_caps(STREAM s)
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
396  {  {
397          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
398            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
         res = res ? lsb_io_uint16(s, &rso->length) : False;  
         res = res ? lsb_io_uint16(s, &rso->flags ) : False;  
         res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
399    
400          return res;          out_uint16_le(s, 6);    /* cache size */
401            out_uint16(s, 0);       /* pad */
402  }  }
403    
404  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  static uint8 canned_caps[] = {
405  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
406          BOOL res = True;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
407            0x00, 0x00, 0x00, 0x00, 0x00,
408          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
410          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
412          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
414          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;          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          rbo->data = s->data + s->offset;  /* Output unknown capability set */
427          s->offset += rbo->bufsize;  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            uint8 type;
479    
480            in_uint32_le(s, rdp_shareid);
481    
482            DEBUG("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid);
483    
484            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          return res;          in_uint16_le(s, message_type);
508  }          in_uint8s(s, 2);        /* pad */
509    
510  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)          switch (message_type)
511  {          {
512          BOOL res = True;                  case RDP_POINTER_MOVE:
513                            in_uint16_le(s, x);
514                            in_uint16_le(s, y);
515                            if (s_check(s))
516                                    ui_move_pointer(x, y);
517                            break;
518    
519          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                  case RDP_POINTER_COLOR:
520          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;                          in_uint16_le(s, cache_idx);
521          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;                          in_uint16_le(s, x);
522          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;                          in_uint16_le(s, y);
523          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;                          in_uint16_le(s, width);
524          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;                          in_uint16_le(s, height);
525          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;                          in_uint16_le(s, masklen);
526          res = res ? lsb_io_uint16(s, &rbo->pad2      ) : False;                          in_uint16_le(s, datalen);
527          res = res ? lsb_io_uint16(s, &rbo->size      ) : False;                          in_uint8p(s, data, datalen);
528          res = res ? lsb_io_uint16(s, &rbo->row_size  ) : False;                          in_uint8p(s, mask, masklen);
529          res = res ? lsb_io_uint16(s, &rbo->final_size) : False;                          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          rbo->data = s->data + s->offset;                  case RDP_POINTER_CACHED:
536          s->offset += rbo->size;                          in_uint16_le(s, cache_idx);
537                            ui_set_cursor(cache_get_cursor(cache_idx));
538                            break;
539    
540          return res;                  default:
541                            DEBUG("Pointer message 0x%x\n", message_type);
542            }
543  }  }
544    
545  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process bitmap updates */
546    static void
547    process_bitmap_updates(STREAM s)
548  {  {
549          COLOURENTRY *entry;          uint16 num_updates;
550            uint16 left, top, right, bottom, width, height;
551            uint16 cx, cy, bpp, compress, bufsize, size;
552            uint8 *data, *bmpdata;
553          int i;          int i;
554    
555          prs_io_uint8(s, &colours->cache_id);          in_uint16_le(s, num_updates);
         lsb_io_uint16(s, &colours->map.ncolours);  
556    
557          for (i = 0; i < colours->map.ncolours; i++)          for (i = 0; i < num_updates; i++)
558          {          {
559                  entry = &colours->map.colours[i];                  in_uint16_le(s, left);
560                  prs_io_uint8(s, &entry->blue);                  in_uint16_le(s, top);
561                  prs_io_uint8(s, &entry->green);                  in_uint16_le(s, right);
562                  prs_io_uint8(s, &entry->red);                  in_uint16_le(s, bottom);
563                  s->offset++;                  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          return True;                  cx = right - left + 1;
570  }                  cy = bottom - top + 1;
   
 BOOL rdp_io_fontcache_order(STREAM s, RDP_FONTCACHE_ORDER *font)  
 {  
         RDP_FONT_GLYPH *glyph;  
         BOOL res = True;  
         int i, j, datasize;  
         uint8 in, out;  
571    
572          res = res ? prs_io_uint8(s, &font->font   ) : False;                  DEBUG("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n",
573          res = res ? prs_io_uint8(s, &font->nglyphs) : False;                        left, top, right, bottom, width, height, compress);
574    
575          for (i = 0; i < font->nglyphs; i++)                  if (!compress)
         {  
                 glyph = &font->glyphs[i];  
                 res = res ? lsb_io_uint16(s, &glyph->character) : False;  
                 res = res ? lsb_io_uint16(s, &glyph->unknown  ) : False;  
                 res = res ? lsb_io_uint16(s, &glyph->baseline ) : False;  
                 res = res ? lsb_io_uint16(s, &glyph->width    ) : False;  
                 res = res ? lsb_io_uint16(s, &glyph->height   ) : False;  
   
                 datasize = (glyph->height * ((glyph->width + 7) / 8) + 3) & ~3;  
                 res = res ? prs_io_uint8s(s, glyph->data, datasize) : False;  
                 for (j = 0; j < datasize; j++)  
576                  {                  {
577                          in = glyph->data[j];                          int y;
578                          out = 0;                          bmpdata = xmalloc(width * height);
579                          if (in & 1) out |= 128;                          for (y = 0; y < height; y++)
580                          if (in & 2) out |= 64;                          {
581                          if (in & 4) out |= 32;                                  in_uint8a(s,
582                          if (in & 8) out |= 16;                                            &bmpdata[(height - y - 1) * width],
583                          if (in & 16) out |= 8;                                            width);
584                          if (in & 32) out |= 4;                          }
585                          if (in & 64) out |= 2;                          ui_paint_bitmap(left, top, cx, cy, width, height,
586                          if (in & 128) out |= 1;                                          bmpdata);
587                          glyph->data[j] = out;                          xfree(bmpdata);
588                            continue;
589                  }                  }
         }  
   
         return res;  
 }  
   
   
 /* CAPABILITIES */  
   
 /* Construct a general capability set */  
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
   
 /* Parse general capability set */  
 BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_GENERAL;  
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_types) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_update    ) : False;  
         res = res ? lsb_io_uint16(s, &caps->remote_unshare) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_level) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3          ) : False;  
   
         return res;  
 }  
   
 /* Construct a bitmap capability set */  
 void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps, int width, int height)  
 {  
         caps->preferred_bpp = 8;  
         caps->receive1bpp = 1;  
         caps->receive4bpp = 1;  
         caps->receive8bpp = 1;  
         caps->width = width;  
         caps->height = height;  
         caps->compression = 1;  
         caps->unknown2 = 1;  
 }  
   
 /* Parse bitmap capability set */  
 BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BITMAP;  
         uint16 pkt_length = length;  
         BOOL res;  
590    
591          res = lsb_io_uint16(s, &pkt_length);                  in_uint8s(s, 2);        /* pad */
592          if (pkt_length != length)                  in_uint16_le(s, size);
593          {                  in_uint8s(s, 4);        /* line_size, final_size */
594                  ERROR("Unrecognised capabilities size\n");                  in_uint8p(s, data, size);
                 return False;  
         }  
595    
596          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  bmpdata = xmalloc(width * height);
597          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;                  if (bitmap_decompress(bmpdata, width, height, data, size))
598          res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;                  {
599          res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;                          ui_paint_bitmap(left, top, cx, cy, width, height,
600          res = res ? lsb_io_uint16(s, &caps->width        ) : False;                                          bmpdata);
601          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;  
 }  
   
 /* Construct an order capability set */  
 void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  
 {  
         caps->xgranularity = 1;  
         caps->ygranularity = 20;  
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
   
 //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;  
   
         caps->support[0] = caps->support[1] = caps->support[2]  
                 = caps->support[3] = caps->support[4] = caps->support[5]  
                 = caps->support[6] = caps->support[8] = caps->support[11]  
                 = caps->support[12] = caps->support[22] = caps->support[28]  
                 = caps->support[29] = caps->support[30] = 1;  
         caps->text_cap_flags = 0x6A1;  
         caps->desk_save_size = 0x38400;  
         caps->unknown2 = 0x4E4;  
 }  
   
 /* Parse order capability set */  
 BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_ORDER;  
         uint16 pkt_length = length;  
         BOOL res;  
602    
603          res = lsb_io_uint16(s, &pkt_length);                  xfree(bmpdata);
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
604          }          }
   
         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;  
 }  
   
 /* Construct a bitmap cache capability set */  
 void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  
 {  
         caps->caches[0].entries = 0x258;  
         caps->caches[0].max_cell_size = 0x100;  
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
605  }  }
606    
607  /* Parse single bitmap cache information structure */  /* Process a palette update */
608  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  static void
609    process_palette(STREAM s)
610  {  {
611          if (!lsb_io_uint16(s, &info->entries      ))          HCOLOURMAP hmap;
612                  return False;          COLOURMAP map;
613    
614          if (!lsb_io_uint16(s, &info->max_cell_size))          in_uint8s(s, 2);        /* pad */
615                  return False;          in_uint16_le(s, map.ncolours);
616            in_uint8s(s, 2);        /* pad */
617            in_uint8p(s, (uint8 *) map.colours, (map.ncolours * 3));
618    
619          return True;          hmap = ui_create_colourmap(&map);
620            ui_set_colourmap(hmap);
621  }  }
622    
623  /* Parse bitmap cache capability set */  /* Process an update PDU */
624  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  static void
625    process_update_pdu(STREAM s)
626  {  {
627          uint16 length = RDP_CAPLEN_BMPCACHE;          uint16 update_type;
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
628    
629          for (i = 0; i < 6; i++)          in_uint16_le(s, update_type);
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
630    
631          for (i = 0; i < 3; i++)          switch (update_type)
632                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;          {
633                    case RDP_UPDATE_ORDERS:
634                            process_orders(s);
635                            break;
636    
637          return res;                  case RDP_UPDATE_BITMAP:
638  }                          process_bitmap_updates(s);
639                            break;
640    
641  /* Construct a control capability set */                  case RDP_UPDATE_PALETTE:
642  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)                          process_palette(s);
643  {                          break;
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
644    
645  /* Parse control capability set */                  case RDP_UPDATE_SYNCHRONIZE:
646  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)                          break;
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
647    
648          res = lsb_io_uint16(s, &pkt_length);                  default:
649          if (pkt_length != length)                          NOTIMP("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
650          }          }
651    
         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;  
652  }  }
653    
654  /* Construct an activation capability set */  /* Process data PDU */
655  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  static void
656    process_data_pdu(STREAM s)
657  {  {
658  }          uint8 data_pdu_type;
659    
660  /* Parse activation capability set */          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
661  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)          in_uint8(s, data_pdu_type);
662  {          in_uint8s(s, 3);        /* compress_type, compress_len */
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
663    
664          res = lsb_io_uint16(s, &pkt_length);          switch (data_pdu_type)
         if (pkt_length != length)  
665          {          {
666                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
667                  return False;                          process_update_pdu(s);
668          }                          break;
   
         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;  
669    
670          return res;                  case RDP_DATA_PDU_POINTER:
671  }                          process_pointer_pdu(s);
672                            break;
673    
674  /* Construct a pointer capability set */                  case RDP_DATA_PDU_BELL:
675  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)                          ui_bell();
676  {                          break;
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
677    
678  /* Parse pointer capability set */                  case RDP_DATA_PDU_LOGON:
679  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)                          /* User logged on */
680  {                          break;
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
681    
682          res = lsb_io_uint16(s, &pkt_length);                  default:
683          if (pkt_length != length)                          NOTIMP("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
684          }          }
   
         res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;  
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
   
         return res;  
685  }  }
686    
687  /* Construct a share capability set */  /* Process incoming packets */
688  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  void
689    rdp_main_loop()
690  {  {
691  }          uint8 type;
692            STREAM s;
 /* Parse share capability set */  
 BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
693    
694          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
695          {          {
696                  ERROR("Unrecognised capabilities size\n");                  switch (type)
697                  return False;                  {
698          }                          case RDP_PDU_DEMAND_ACTIVE:
699                                    process_demand_active(s);
700                                    break;
701    
702          res = res ? lsb_io_uint16(s, &caps->userid) : False;                          case RDP_PDU_DEACTIVATE:
703          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                                  break;
704    
705          return res;                          case RDP_PDU_DATA:
706  }                                  process_data_pdu(s);
707                                    break;
708    
709  /* Construct a colour cache capability set */                          default:
710  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)                                  NOTIMP("PDU %d\n", type);
711  {                  }
712          caps->cache_size = 6;          }
713  }  }
714    
715  /* Parse colour cache capability set */  /* Establish a connection up to the RDP layer */
716  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
717    rdp_connect(char *server, uint32 flags, char *domain, char *password,
718                char *command, char *directory)
719  {  {
720          uint16 length = RDP_CAPLEN_COLCACHE;          if (!sec_connect(server))
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
721                  return False;                  return False;
         }  
722    
723          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          rdp_send_logon_info(flags, domain, username, password,
724          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;                              command, directory);
725            return True;
         return res;  
726  }  }
727    
728  uint8 canned_caps[] = {  /* Disconnect from the RDP layer */
729  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  void
730  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  rdp_disconnect()
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x01,  
 0x00,0x00,0x00,0x0E,0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x34,0x00,0xFE,  
 0x00,0x04,0x00,0xFE,0x00,0x04,0x00,0xFE,0x00,0x08,0x00,0xFE,0x00,0x08,0x00,0xFE,  
 0x00,0x10,0x00,0xFE,0x00,0x20,0x00,0xFE,0x00,0x40,0x00,0xFE,0x00,0x80,0x00,0xFE,  
 0x00,0x00,0x01,0x40,0x00,0x00,0x08,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00  
 };  
   
 /* Insert canned capabilities */  
 BOOL rdp_io_unknown_caps(STREAM s, void *caps)  
731  {  {
732          uint16 length = 0x58;          sec_disconnect();
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;  
   
         return res;  
733  }  }

Legend:
Removed from v.9  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26