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

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

  ViewVC Help
Powered by ViewVC 1.1.26