/[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 340 by forsberg, Thu Mar 6 14:11:17 2003 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-2002
5        
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  /* Establish a connection up to the RDP layer */  extern uint16 mcs_userid;
24  HCONN rdp_connect(char *server, int width, int height)  extern char username[16];
25  {  extern BOOL bitmap_compression;
26          HCONN conn;  extern BOOL orders;
27    extern BOOL 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);  
 }  
32    
33  /* Construct an RDP header */  #if WITH_DEBUG
34  void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,  static uint32 packetno;
35                       uint16 userid)  #endif
 {  
         hdr->length = length;  
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
 }  
36    
37  /* Parse an RDP header */  /* Initialise an RDP packet */
38  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  static STREAM
39    rdp_init(int maxlen)
40  {  {
41          BOOL res = True;          STREAM s;
42    
43          res = res ? lsb_io_uint16(s, &hdr->length  ) : False;          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 6);
44          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;  
45    
46          return res;          return s;
47  }  }
48    
49  /* Construct a data header */  /* Send an RDP packet */
50  void rdp_make_data_header(RDP_DATA_HEADER *hdr, uint32 shareid,  static void
51                            uint16 length, uint16 data_pdu_type)  rdp_send(STREAM s, uint8 pdu_type)
52  {  {
53          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;  
 }  
54    
55  /* Parse a data header */          s_pop_layer(s, rdp_hdr);
56  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)          length = s->end - s->p;
 {  
         BOOL res = True;  
57    
58          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;          out_uint16_le(s, length);
59          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;          out_uint16_le(s, (pdu_type | 0x10));    /* Version 1 */
60          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;  
61    
62          return res;          sec_send(s, encryption ? SEC_ENCRYPT : 0);
63  }  }
64    
65  BOOL rdp_io_present(STREAM s, uint32 *present, uint8 flags, int size)  /* Receive an RDP packet */
66    static STREAM
67    rdp_recv(uint8 * type)
68  {  {
69          uint8 bits;          static STREAM rdp_s;
70          int i;          uint16 length, pdu_type;
   
         if (flags & RDP_ORDER_SMALL)  
         {  
                 size--;  
         }  
71    
72          if (flags & RDP_ORDER_TINY)          if ((rdp_s == NULL) || (next_packet >= rdp_s->end))
73          {          {
74                  if (size < 2)                  rdp_s = sec_recv();
75                          return False;                  if (rdp_s == NULL)
76                            return NULL;
77    
78                  size -= 2;                  next_packet = rdp_s->p;
79          }          }
80            else
         *present = 0;  
         for (i = 0; i < size; i++)  
81          {          {
82                  prs_io_uint8(s, &bits);                  rdp_s->p = next_packet;
                 *present |= bits << (i * 8);  
83          }          }
84    
85          return True;          in_uint16_le(rdp_s, length);
86  }          /* 32k packets are really 8, keepalive fix */
87            if (length == 0x8000)
 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;  
         }  
         else  
88          {          {
89                  res = lsb_io_uint16(s, coord);                  next_packet += 8;
90                    *type = 0;
91                    return rdp_s;
92          }          }
93            in_uint16_le(rdp_s, pdu_type);
94            in_uint8s(rdp_s, 2);    /* userid */
95            *type = pdu_type & 0xf;
96    
97          return res;  #if WITH_DEBUG
98  }          DEBUG(("RDP packet #%d, (type %x):\n", ++packetno, *type));
99            hexdump(next_packet, length);
100  BOOL rdp_io_colour(STREAM s, uint8 *colour)  #endif /*  */
 {  
         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;  
101    
102          if (present & 4)          next_packet += length;
103                  res = res ? prs_io_uint8(s, &brush->style) : False;          return rdp_s;
   
         if (present & 8)  
                 res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;  
   
         if (present & 16)  
                 res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;  
   
         return res;  
104  }  }
105    
106  /* Construct a confirm/demand active PDU */  /* Initialise an RDP data packet */
107  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid,  static STREAM
108                                  int width, int height)  rdp_init_data(int maxlen)
109  {  {
110          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));  
111    
112          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);
113                  + 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;  
114    
115          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);  
116  }  }
117    
118  /* Parse a confirm/demand active PDU */  /* Send an RDP data packet */
119  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  static void
120    rdp_send_data(STREAM s, uint8 data_pdu_type)
121  {  {
         uint16 capset;  
122          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;  
 }  
123    
124  /* Construct a control PDU */          s_pop_layer(s, rdp_hdr);
125  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)          length = s->end - s->p;
 {  
         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;  
   
         res = res ? lsb_io_uint16(s, &pdu->action   ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;  
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
   
         return res;  
 }  
   
 /* Construct a synchronisation PDU */  
 void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  
 {  
         pdu->type = 1;  
         pdu->userid = userid;  
 }  
126    
127  /* Parse a synchronisation PDU */          out_uint16_le(s, length);
128  BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
129  {          out_uint16_le(s, (mcs_userid + 1001));
         BOOL res = True;  
130    
131          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          out_uint32_le(s, rdp_shareid);
132          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          out_uint8(s, 0);        /* pad */
133            out_uint8(s, 1);        /* streamid */
134            out_uint16_le(s, (length - 14));
135            out_uint8(s, data_pdu_type);
136            out_uint8(s, 0);        /* compress_type */
137            out_uint16(s, 0);       /* compress_len */
138    
139          return res;          sec_send(s, encryption ? SEC_ENCRYPT : 0);
140  }  }
141    
142  /* Parse a single input event */  /* Output a string in Unicode */
143  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  void
144    rdp_out_unistr(STREAM s, char *string, int len)
145  {  {
146          BOOL res = True;          int i = 0, j = 0;
   
         res = res ? lsb_io_uint32(s, &evt->event_time)   : False;  
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
         res = res ? lsb_io_uint16(s, &evt->device_flags) : False;  
147    
148          if (!res)          len += 2;
                 return False;  
149    
150          switch (evt->message_type)          while (i < len)
151          {          {
152          case RDP_INPUT_CODEPOINT:                  s->p[i++] = string[j++];
153          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;  
154          }          }
155    
156          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;  
157  }  }
158    
159  /* Parse an input PDU */  /* Parse a logon info packet */
160  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
161    rdp_send_logon_info(uint32 flags, char *domain, char *user,
162                        char *password, char *program, char *directory)
163  {  {
164          BOOL res = True;          int len_domain = 2 * strlen(domain);
165          int i;          int len_user = 2 * strlen(user);
166            int len_password = 2 * strlen(password);
167          res = res ? lsb_io_uint16(s, &pdu->num_events) : False;          int len_program = 2 * strlen(program);
168          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;          int len_directory = 2 * strlen(directory);
169            uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
170            STREAM s;
171    
172          if (pdu->num_events > RDP_MAX_EVENTS)          s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
173          {                       + len_program + len_directory + 10);
                 ERROR("Too many events in one PDU\n");  
                 return False;  
         }  
174    
175          for (i = 0; i < pdu->num_events; i++)          out_uint32(s, 0);
176          {          out_uint32_le(s, flags);
177                  res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;          out_uint16_le(s, len_domain);
178          }          out_uint16_le(s, len_user);
179            out_uint16_le(s, len_password);
180            out_uint16_le(s, len_program);
181            out_uint16_le(s, len_directory);
182            rdp_out_unistr(s, domain, len_domain);
183            rdp_out_unistr(s, user, len_user);
184            rdp_out_unistr(s, password, len_password);
185            rdp_out_unistr(s, program, len_program);
186            rdp_out_unistr(s, directory, len_directory);
187    
188          return res;          s_mark_end(s);
189            sec_send(s, sec_flags);
190  }  }
191    
192  /* Construct a font information PDU */  /* Send a control PDU */
193  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)  static void
194    rdp_send_control(uint16 action)
195  {  {
196          pdu->num_fonts = 0;          STREAM s;
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
 }  
197    
198  /* Parse a font information structure */          s = rdp_init_data(8);
 BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  
 {  
         BOOL res = True;  
199    
200          res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;          out_uint16_le(s, action);
201          res = res ? lsb_io_uint16(s, &font->flags    ) : False;          out_uint16(s, 0);       /* userid */
202          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;  
203    
204          return res;          s_mark_end(s);
205            rdp_send_data(s, RDP_DATA_PDU_CONTROL);
206  }  }
207    
208  /* Parse a font information PDU */  /* Send a synchronisation PDU */
209  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  static void
210    rdp_send_synchronise(void)
211  {  {
212          BOOL res = True;          STREAM s;
         int i;  
   
         res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  
213    
214          if (pdu->num_fonts > RDP_MAX_FONTS)          s = rdp_init_data(4);
         {  
                 ERROR("Too many fonts in one PDU\n");  
                 return False;  
         }  
215    
216          for (i = 0; i < pdu->num_fonts; i++)          out_uint16_le(s, 1);    /* type */
217          {          out_uint16_le(s, 1002);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
         }  
218    
219          return res;          s_mark_end(s);
220            rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
221  }  }
222    
223  /* Parse a pointer PDU */  /* Send a single input event */
224  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  void
225    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
226  {  {
227          BOOL res = True;          STREAM s;
   
         res = res ? lsb_io_uint16(s, &ptr->message) : False;  
         res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;  
228    
229          switch (ptr->message)          s = rdp_init_data(16);
         {  
                 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;  
 }  
230    
231  /* Parse an update PDU */          out_uint16_le(s, 1);    /* number of events */
232  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)          out_uint16(s, 0);       /* pad */
 {  
         BOOL res = True;  
233    
234          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;          out_uint32_le(s, time);
235          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;          out_uint16_le(s, message_type);
236            out_uint16_le(s, device_flags);
237            out_uint16_le(s, param1);
238            out_uint16_le(s, param2);
239    
240          return res;          s_mark_end(s);
241            rdp_send_data(s, RDP_DATA_PDU_INPUT);
242  }  }
243    
244    /* Send an (empty) font information PDU */
245  /* PRIMARY ORDERS */  static void
246    rdp_send_fonts(uint16 seq)
 /* Parse an destination blt order */  
 BOOL rdp_io_destblt_order(STREAM s, DESTBLT_ORDER *os, uint32 present, BOOL delta)  
247  {  {
248          if (present & 0x01)          STREAM s;
                 rdp_io_coord(s, &os->x, delta);  
249    
250          if (present & 0x02)          s = rdp_init_data(8);
                 rdp_io_coord(s, &os->y, delta);  
251    
252          if (present & 0x04)          out_uint16(s, 0);       /* number of fonts */
253                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 0x3e); /* unknown */
254            out_uint16_le(s, seq);  /* unknown */
255            out_uint16_le(s, 0x32); /* entry size */
256    
257          if (present & 0x08)          s_mark_end(s);
258                  rdp_io_coord(s, &os->cy, delta);          rdp_send_data(s, RDP_DATA_PDU_FONT2);
   
         if (present & 0x10)  
                 prs_io_uint8(s, &os->opcode);  
   
         return PRS_ERROR(s);  
259  }  }
260    
261  /* Parse an pattern blt order */  /* Output general capability set */
262  BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  static void
263    rdp_out_general_caps(STREAM s)
264  {  {
265          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_GENERAL);
266                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_GENERAL);
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->y, delta);  
267    
268          if (present & 0x0004)          out_uint16_le(s, 1);    /* OS major type */
269                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 3);    /* OS minor type */
270            out_uint16_le(s, 0x200);        /* Protocol version */
271          if (present & 0x0008)          out_uint16(s, 0);       /* Pad */
272                  rdp_io_coord(s, &os->cy, delta);          out_uint16(s, 0);       /* Compression types */
273            out_uint16(s, 0);       /* Pad */
274          if (present & 0x0010)          out_uint16(s, 0);       /* Update capability */
275                  prs_io_uint8(s, &os->opcode);          out_uint16(s, 0);       /* Remote unshare capability */
276            out_uint16(s, 0);       /* Compression level */
277          if (present & 0x0020)          out_uint16(s, 0);       /* Pad */
                 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);  
278  }  }
279    
280  /* Parse an screen blt order */  /* Output bitmap capability set */
281  BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  static void
282    rdp_out_bitmap_caps(STREAM s)
283  {  {
284          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_BITMAP);
285                  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);  
   
         if (present & 0x0040)  
                 rdp_io_coord(s, &os->srcy, delta);  
286    
287          return PRS_ERROR(s);          out_uint16_le(s, 8);    /* Preferred BPP */
288            out_uint16_le(s, 1);    /* Receive 1 BPP */
289            out_uint16_le(s, 1);    /* Receive 4 BPP */
290            out_uint16_le(s, 1);    /* Receive 8 BPP */
291            out_uint16_le(s, 800);  /* Desktop width */
292            out_uint16_le(s, 600);  /* Desktop height */
293            out_uint16(s, 0);       /* Pad */
294            out_uint16(s, 0);       /* Allow resize */
295            out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */
296            out_uint16(s, 0);       /* Unknown */
297            out_uint16_le(s, 1);    /* Unknown */
298            out_uint16(s, 0);       /* Pad */
299  }  }
300    
301  /* Parse a line order */  /* Output order capability set */
302  BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  static void
303    rdp_out_order_caps(STREAM s)
304  {  {
305          if (present & 0x0001)          uint8 order_caps[32];
                 lsb_io_uint16(s, &os->mixmode);  
306    
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->startx, delta);  
307    
308          if (present & 0x0004)          memset(order_caps, 0, 32);
309                  rdp_io_coord(s, &os->starty, delta);          order_caps[0] = 1;      /* dest blt */
310            order_caps[1] = 1;      /* pat blt */
311            order_caps[2] = 1;      /* screen blt */
312            order_caps[3] = 1;      /* required for memblt? */
313            order_caps[8] = 1;      /* line */
314            order_caps[9] = 1;      /* line */
315            order_caps[10] = 1;     /* rect */
316            order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */
317            order_caps[13] = 1;     /* memblt */
318            order_caps[14] = 1;     /* triblt */
319            order_caps[22] = 1;     /* polyline */
320            order_caps[27] = 1;     /* text2 */
321            out_uint16_le(s, RDP_CAPSET_ORDER);
322            out_uint16_le(s, RDP_CAPLEN_ORDER);
323    
324          if (present & 0x0008)          out_uint8s(s, 20);      /* Terminal desc, pad */
325                  rdp_io_coord(s, &os->endx, delta);          out_uint16_le(s, 1);    /* Cache X granularity */
326            out_uint16_le(s, 20);   /* Cache Y granularity */
327          if (present & 0x0010)          out_uint16(s, 0);       /* Pad */
328                  rdp_io_coord(s, &os->endy, delta);          out_uint16_le(s, 1);    /* Max order level */
329            out_uint16_le(s, 0x147);        /* Number of fonts */
330          if (present & 0x0020)          out_uint16_le(s, 0x2a); /* Capability flags */
331                  rdp_io_colour(s, &os->bgcolour);          out_uint8p(s, order_caps, 32);  /* Orders supported */
332            out_uint16_le(s, 0x6a1);        /* Text capability flags */
333          if (present & 0x0040)          out_uint8s(s, 6);       /* Pad */
334                  prs_io_uint8(s, &os->opcode);          out_uint32_le(s, desktop_save == False ? 0 : 0x38400);  /* Desktop cache size */
335            out_uint32(s, 0);       /* Unknown */
336          rdp_io_pen(s, &os->pen, present >> 7);          out_uint32_le(s, 0x4e4);        /* Unknown */
   
         return PRS_ERROR(s);  
337  }  }
338    
339  /* Parse an opaque rectangle order */  /* Output bitmap cache capability set */
340  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  static void
341    rdp_out_bmpcache_caps(STREAM s)
342  {  {
343          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
344                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
   
         if (present & 0x02)  
                 rdp_io_coord(s, &os->y, delta);  
345    
346          if (present & 0x04)          out_uint8s(s, 24);      /* unused */
347                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 0x258);        /* entries */
348            out_uint16_le(s, 0x100);        /* max cell size */
349          if (present & 0x08)          out_uint16_le(s, 0x12c);        /* entries */
350                  rdp_io_coord(s, &os->cy, delta);          out_uint16_le(s, 0x400);        /* max cell size */
351            out_uint16_le(s, 0x106);        /* entries */
352          if (present & 0x10)          out_uint16_le(s, 0x1000);       /* max cell size */
                 prs_io_uint8(s, &os->colour);  
   
         return PRS_ERROR(s);  
353  }  }
354    
355  /* Parse a desktop save order */  /* Output control capability set */
356  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  static void
357    rdp_out_control_caps(STREAM s)
358  {  {
359          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_CONTROL);
360                  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);  
   
         if (present & 0x08)  
                 rdp_io_coord(s, &os->right, delta);  
361    
362          if (present & 0x10)          out_uint16(s, 0);       /* Control capabilities */
363                  rdp_io_coord(s, &os->bottom, delta);          out_uint16(s, 0);       /* Remote detach */
364            out_uint16_le(s, 2);    /* Control interest */
365          if (present & 0x20)          out_uint16_le(s, 2);    /* Detach interest */
                 prs_io_uint8(s, &os->action);  
   
         return PRS_ERROR(s);  
366  }  }
367    
368  /* Parse a memory blt order */  /* Output activation capability set */
369  BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  static void
370    rdp_out_activate_caps(STREAM s)
371  {  {
372          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
373          {          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);  
   
         if (present & 0x0100)  
                 lsb_io_uint16(s, &os->cache_idx);  
374    
375          return PRS_ERROR(s);          out_uint16(s, 0);       /* Help key */
376            out_uint16(s, 0);       /* Help index key */
377            out_uint16(s, 0);       /* Extended help key */
378            out_uint16(s, 0);       /* Window activate */
379  }  }
380    
381  /* Parse a 3-way blt order */  /* Output pointer capability set */
382  BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta)  static void
383    rdp_out_pointer_caps(STREAM s)
384  {  {
385          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_POINTER);
386          {          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);  
   
         rdp_io_brush(s, &os->brush, present >> 10);  
387    
388          if (present & 0x008000)          out_uint16(s, 0);       /* Colour pointer */
389                  lsb_io_uint16(s, &os->cache_idx);          out_uint16_le(s, 20);   /* Cache size */
   
         if (present & 0x010000)  
                 lsb_io_uint16(s, &os->unknown);  
   
         return PRS_ERROR(s);  
390  }  }
391    
392  /* Parse a text order */  /* Output share capability set */
393  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  static void
394    rdp_out_share_caps(STREAM s)
395  {  {
396          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_SHARE);
397                  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);  
   
         if (present & 0x000400)  
                 lsb_io_uint16(s, &os->boxleft);  
398    
399          if (present & 0x000800)          out_uint16(s, 0);       /* userid */
400                  lsb_io_uint16(s, &os->boxtop);          out_uint16(s, 0);       /* pad */
   
         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);  
401  }  }
402    
403    /* Output colour cache capability set */
404  /* SECONDARY ORDERS */  static void
405    rdp_out_colcache_caps(STREAM s)
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
406  {  {
407          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
408            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;  
409    
410          return res;          out_uint16_le(s, 6);    /* cache size */
411            out_uint16(s, 0);       /* pad */
412  }  }
413    
414  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  static uint8 canned_caps[] = {
415  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
416          BOOL res = True;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
417            0x00, 0x00, 0x00, 0x00, 0x00,
418          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
420          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
422          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
424          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425            0x0C, 0x00, 0x08, 0x00, 0x01,
426            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
427            0x10, 0x00, 0x34, 0x00, 0xFE,
428            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
429            0xFE, 0x00, 0x08, 0x00, 0xFE,
430            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
431            0xFE, 0x00, 0x80, 0x00, 0xFE,
432            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
433            0x02, 0x00, 0x00, 0x00
434    };
435    
436          rbo->data = s->data + s->offset;  /* Output unknown capability set */
437          s->offset += rbo->bufsize;  static void
438    rdp_out_unknown_caps(STREAM s)
439    {
440            out_uint16_le(s, RDP_CAPSET_UNKNOWN);
441            out_uint16_le(s, 0x58);
442    
443            out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
444    }
445    
446    /* Send a confirm active PDU */
447    static void
448    rdp_send_confirm_active(void)
449    {
450            STREAM s;
451            uint16 caplen =
452                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
453                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
454                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
455                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
456    
457            s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));
458    
459            out_uint32_le(s, rdp_shareid);
460            out_uint16_le(s, 0x3ea);        /* userid */
461            out_uint16_le(s, sizeof(RDP_SOURCE));
462            out_uint16_le(s, caplen);
463    
464            out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
465            out_uint16_le(s, 0xd);  /* num_caps */
466            out_uint8s(s, 2);       /* pad */
467    
468            rdp_out_general_caps(s);
469            rdp_out_bitmap_caps(s);
470            rdp_out_order_caps(s);
471            rdp_out_bmpcache_caps(s);
472            rdp_out_colcache_caps(s);
473            rdp_out_activate_caps(s);
474            rdp_out_control_caps(s);
475            rdp_out_pointer_caps(s);
476            rdp_out_share_caps(s);
477            rdp_out_unknown_caps(s);
478    
479            s_mark_end(s);
480            rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);
481    }
482    
483    /* Respond to a demand active PDU */
484    static void
485    process_demand_active(STREAM s)
486    {
487            uint8 type;
488    
489            in_uint32_le(s, rdp_shareid);
490    
491            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));
492    
493            rdp_send_confirm_active();
494            rdp_send_synchronise();
495            rdp_send_control(RDP_CTL_COOPERATE);
496            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
497            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
498            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
499            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
500            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
501            rdp_send_fonts(1);
502            rdp_send_fonts(2);
503            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
504            reset_order_state();
505    }
506    
507    /* Process a pointer PDU */
508    static void
509    process_pointer_pdu(STREAM s)
510    {
511            uint16 message_type;
512            uint16 x, y, width, height, cache_idx, masklen, datalen;
513            uint8 *mask, *data;
514            HCURSOR cursor;
515    
516          return res;          in_uint16_le(s, message_type);
517  }          in_uint8s(s, 2);        /* pad */
518    
519  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)          switch (message_type)
520  {          {
521          BOOL res = True;                  case RDP_POINTER_MOVE:
522                            in_uint16_le(s, x);
523                            in_uint16_le(s, y);
524                            if (s_check(s))
525                                    ui_move_pointer(x, y);
526                            break;
527    
528          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                  case RDP_POINTER_COLOR:
529          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;                          in_uint16_le(s, cache_idx);
530          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;                          in_uint16_le(s, x);
531          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;                          in_uint16_le(s, y);
532          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;                          in_uint16_le(s, width);
533          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;                          in_uint16_le(s, height);
534          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;                          in_uint16_le(s, masklen);
535          res = res ? lsb_io_uint16(s, &rbo->pad2      ) : False;                          in_uint16_le(s, datalen);
536          res = res ? lsb_io_uint16(s, &rbo->size      ) : False;                          in_uint8p(s, data, datalen);
537          res = res ? lsb_io_uint16(s, &rbo->row_size  ) : False;                          in_uint8p(s, mask, masklen);
538          res = res ? lsb_io_uint16(s, &rbo->final_size) : False;                          cursor = ui_create_cursor(x, y, width, height, mask, data);
539                            ui_set_cursor(cursor);
540                            cache_put_cursor(cache_idx, cursor);
541                            break;
542    
543          rbo->data = s->data + s->offset;                  case RDP_POINTER_CACHED:
544          s->offset += rbo->size;                          in_uint16_le(s, cache_idx);
545                            ui_set_cursor(cache_get_cursor(cache_idx));
546                            break;
547    
548          return res;                  default:
549                            DEBUG(("Pointer message 0x%x\n", message_type));
550            }
551  }  }
552    
553  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process bitmap updates */
554    static void
555    process_bitmap_updates(STREAM s)
556  {  {
557          COLOURENTRY *entry;          uint16 num_updates;
558            uint16 left, top, right, bottom, width, height;
559            uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
560            uint8 *data, *bmpdata;
561          int i;          int i;
562    
563          prs_io_uint8(s, &colours->cache_id);          in_uint16_le(s, num_updates);
         lsb_io_uint16(s, &colours->map.ncolours);  
564    
565          for (i = 0; i < colours->map.ncolours; i++)          for (i = 0; i < num_updates; i++)
566          {          {
567                  entry = &colours->map.colours[i];                  in_uint16_le(s, left);
568                  prs_io_uint8(s, &entry->blue);                  in_uint16_le(s, top);
569                  prs_io_uint8(s, &entry->green);                  in_uint16_le(s, right);
570                  prs_io_uint8(s, &entry->red);                  in_uint16_le(s, bottom);
571                  s->offset++;                  in_uint16_le(s, width);
572          }                  in_uint16_le(s, height);
573                    in_uint16_le(s, bpp);
574                    Bpp = (bpp + 7) / 8;
575                    in_uint16_le(s, compress);
576                    in_uint16_le(s, bufsize);
577    
578          return True;                  cx = right - left + 1;
579  }                  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;  
580    
581          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",
582          res = res ? prs_io_uint8(s, &font->nglyphs) : False;                         left, top, right, bottom, width, height, compress));
583    
584          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++)  
585                  {                  {
586                          in = glyph->data[j];                          int y;
587                          out = 0;                          bmpdata = xmalloc(width * height * Bpp);
588                          if (in & 1) out |= 128;                          for (y = 0; y < height; y++)
589                          if (in & 2) out |= 64;                          {
590                          if (in & 4) out |= 32;                                  in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
591                          if (in & 8) out |= 16;                                            width * Bpp);
592                          if (in & 16) out |= 8;                          }
593                          if (in & 32) out |= 4;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
594                          if (in & 64) out |= 2;                          xfree(bmpdata);
595                          if (in & 128) out |= 1;                          continue;
                         glyph->data[j] = out;  
596                  }                  }
         }  
   
         return res;  
 }  
597    
598                    in_uint8s(s, 2);        /* pad */
599  /* CAPABILITIES */                  in_uint16_le(s, size);
600                    in_uint8s(s, 4);        /* line_size, final_size */
601  /* Construct a general capability set */                  in_uint8p(s, data, size);
602  void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)                  bmpdata = xmalloc(width * height * Bpp);
603  {                  if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
604          caps->os_major_type = 1;                  {
605          caps->os_minor_type = 3;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
606          caps->ver_protocol = 0x200;                  }
607                    xfree(bmpdata);
608            }
609  }  }
610    
611  /* Parse general capability set */  /* Process a palette update */
612  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  static void
613    process_palette(STREAM s)
614  {  {
615          uint16 length = RDP_CAPLEN_GENERAL;          COLOURENTRY *entry;
616          uint16 pkt_length = length;          COLOURMAP map;
617          BOOL res;          HCOLOURMAP hmap;
618            int i;
619    
620          res = lsb_io_uint16(s, &pkt_length);          in_uint8s(s, 2);        /* pad */
621          if (pkt_length != length)          in_uint16_le(s, map.ncolours);
622          {          in_uint8s(s, 2);        /* pad */
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
623    
624          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          map.colours = xmalloc(3 * map.ncolours);
         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;  
625    
626          res = lsb_io_uint16(s, &pkt_length);          for (i = 0; i < map.ncolours; i++)
         if (pkt_length != length)  
627          {          {
628                  ERROR("Unrecognised capabilities size\n");                  entry = &map.colours[i];
629                  return False;                  in_uint8(s, entry->red);
630                    in_uint8(s, entry->green);
631                    in_uint8(s, entry->blue);
632          }          }
633    
634          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;          hmap = ui_create_colourmap(&map);
635          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;          ui_set_colourmap(hmap);
         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;  
 }  
   
 /* 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;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
636    
637          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;          xfree(map.colours);
         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;  
638  }  }
639    
640  /* Parse single bitmap cache information structure */  /* Process an update PDU */
641  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  static void
642    process_update_pdu(STREAM s)
643  {  {
644          if (!lsb_io_uint16(s, &info->entries      ))          uint16 update_type;
                 return False;  
   
         if (!lsb_io_uint16(s, &info->max_cell_size))  
                 return False;  
   
         return True;  
 }  
645    
646  /* Parse bitmap cache capability set */          in_uint16_le(s, update_type);
 BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BMPCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
647    
648          res = lsb_io_uint16(s, &pkt_length);          switch (update_type)
         if (pkt_length != length)  
649          {          {
650                  ERROR("Unrecognised capabilities size\n");                  case RDP_UPDATE_ORDERS:
651                  return False;                          process_orders(s);
652          }                          break;
   
         for (i = 0; i < 6; i++)  
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
   
         for (i = 0; i < 3; i++)  
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
653    
654          return res;                  case RDP_UPDATE_BITMAP:
655  }                          process_bitmap_updates(s);
656                            break;
657    
658  /* Construct a control capability set */                  case RDP_UPDATE_PALETTE:
659  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)                          process_palette(s);
660  {                          break;
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
661    
662  /* Parse control capability set */                  case RDP_UPDATE_SYNCHRONIZE:
663  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)                          break;
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
664    
665          res = lsb_io_uint16(s, &pkt_length);                  default:
666          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
667          }          }
668    
         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;  
669  }  }
670    
671  /* Construct an activation capability set */  /* Process data PDU */
672  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  static void
673    process_data_pdu(STREAM s)
674  {  {
675  }          uint8 data_pdu_type;
676    
677  /* Parse activation capability set */          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
678  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)          in_uint8(s, data_pdu_type);
679  {          in_uint8s(s, 3);        /* compress_type, compress_len */
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
680    
681          res = lsb_io_uint16(s, &pkt_length);          switch (data_pdu_type)
         if (pkt_length != length)  
682          {          {
683                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
684                  return False;                          process_update_pdu(s);
685          }                          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;  
686    
687          return res;                  case RDP_DATA_PDU_POINTER:
688  }                          process_pointer_pdu(s);
689                            break;
690    
691  /* Construct a pointer capability set */                  case RDP_DATA_PDU_BELL:
692  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)                          ui_bell();
693  {                          break;
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
694    
695  /* Parse pointer capability set */                  case RDP_DATA_PDU_LOGON:
696  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)                          /* User logged on */
697  {                          break;
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
698    
699          res = lsb_io_uint16(s, &pkt_length);                  default:
700          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
701          }          }
   
         res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;  
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
   
         return res;  
 }  
   
 /* Construct a share capability set */  
 void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  
 {  
702  }  }
703    
704  /* Parse share capability set */  /* Process incoming packets */
705  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)  void
706    rdp_main_loop(void)
707  {  {
708          uint16 length = RDP_CAPLEN_SHARE;          uint8 type;
709          uint16 pkt_length = length;          STREAM s;
         BOOL res;  
710    
711          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
712          {          {
713                  ERROR("Unrecognised capabilities size\n");                  switch (type)
714                  return False;                  {
715          }                          case RDP_PDU_DEMAND_ACTIVE:
716                                    process_demand_active(s);
717          res = res ? lsb_io_uint16(s, &caps->userid) : False;                                  break;
         res = res ? lsb_io_uint16(s, &caps->pad   ) : False;  
718    
719          return res;                          case RDP_PDU_DEACTIVATE:
720  }                                  break;
721    
722  /* Construct a colour cache capability set */                          case RDP_PDU_DATA:
723  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)                                  process_data_pdu(s);
724  {                                  break;
         caps->cache_size = 6;  
 }  
725    
726  /* Parse colour cache capability set */                          case 0:
727  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)                                  break;
 {  
         uint16 length = RDP_CAPLEN_COLCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
728    
729          res = lsb_io_uint16(s, &pkt_length);                          default:
730          if (pkt_length != length)                                  unimpl("PDU %d\n", type);
731          {                  }
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
732          }          }
   
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
   
         return res;  
733  }  }
734    
735  uint8 canned_caps[] = {  /* Establish a connection up to the RDP layer */
736  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  BOOL
737  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
738  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,              char *command, char *directory)
 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)  
739  {  {
740          uint16 length = 0x58;          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");  
741                  return False;                  return False;
         }  
742    
743          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;          rdp_send_logon_info(flags, domain, username, password, command, directory);
744            return True;
745    }
746    
747          return res;  /* Disconnect from the RDP layer */
748    void
749    rdp_disconnect(void)
750    {
751            sec_disconnect();
752  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26