/[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 82 by astrand, Tue Jul 30 07:18:48 2002 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP layer     Protocol services - RDP layer
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2001
5        
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  /* Establish a connection up to the RDP layer */  extern uint16 mcs_userid;
24  HCONN rdp_connect(char *server, 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;  
   
         res = prs_io_uint8(s, colour);  
         s->offset += 2;  
   
         return res;  
 }  
   
 BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours)  
 {  
         int datasize;  
   
         lsb_io_uint16(s, &colours->ncolours);  
         datasize = colours->ncolours * 3;  
   
         if (datasize > sizeof(colours->colours))  
                 return False;  
   
         memcpy(colours->colours, s->data + s->offset, datasize);  
         s->offset += datasize;  
         return True;  
 }  
   
 BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds)  
 {  
         uint8 present;  
   
         prs_io_uint8(s, &present);  
   
         if (present & 1)  
                 rdp_io_coord(s, &bounds->left, False);  
         else if (present & 16)  
                 rdp_io_coord(s, &bounds->left, True);  
   
         if (present & 2)  
                 rdp_io_coord(s, &bounds->top, False);  
         else if (present & 32)  
                 rdp_io_coord(s, &bounds->top, True);  
   
         if (present & 4)  
                 rdp_io_coord(s, &bounds->right, False);  
         else if (present & 64)  
                 rdp_io_coord(s, &bounds->right, True);  
   
         if (present & 8)  
                 rdp_io_coord(s, &bounds->bottom, False);  
         else if (present & 128)  
                 rdp_io_coord(s, &bounds->bottom, True);  
   
         return True;  
 }  
   
 BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present)  
 {  
         BOOL res = True;  
   
         if (present & 1)  
                 res = res ? prs_io_uint8(s, &pen->style) : False;  
   
         if (present & 2)  
                 res = res ? prs_io_uint8(s, &pen->width) : False;  
   
         if (present & 4)  
                 res = res ? rdp_io_colour(s, &pen->colour) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_brush(STREAM s, BRUSH *brush, uint32 present)  
 {  
         BOOL res = True;  
   
         if (present & 1)  
                 res = res ? prs_io_uint8(s, &brush->xorigin) : False;  
   
         if (present & 2)  
                 res = res ? prs_io_uint8(s, &brush->yorigin) : False;  
   
         if (present & 4)  
                 res = res ? prs_io_uint8(s, &brush->style) : False;  
85    
86          if (present & 8)  #if WITH_DEBUG
87                  res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;          DEBUG(("RDP packet (type %x):\n", *type));
88            hexdump(next_packet, length);
89    #endif /*  */
90    
91          if (present & 16)          next_packet += length;
92                  res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;          return rdp_s;
   
         return res;  
93  }  }
94    
95  /* Construct a confirm/demand active PDU */  /* Initialise an RDP data packet */
96  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid,  static STREAM
97                                  int width, int height)  rdp_init_data(int maxlen)
98  {  {
99          memset(pdu, 0, sizeof(*pdu));          STREAM s;
         pdu->shareid = shareid;  
         pdu->userid  = 1002;  
         pdu->source_len = sizeof(RDP_SOURCE);  
         memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));  
100    
101          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);
102                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          s_push_layer(s, rdp_hdr, 18);
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
103    
104          rdp_make_general_caps (&pdu->general_caps );          return s;
         rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);  
         rdp_make_order_caps   (&pdu->order_caps   );  
         rdp_make_bmpcache_caps(&pdu->bmpcache_caps);  
         rdp_make_control_caps (&pdu->control_caps );  
         rdp_make_activate_caps(&pdu->activate_caps);  
         rdp_make_pointer_caps (&pdu->pointer_caps );  
         rdp_make_share_caps   (&pdu->share_caps, userid);  
         rdp_make_colcache_caps(&pdu->colcache_caps);  
105  }  }
106    
107  /* Parse a confirm/demand active PDU */  /* Send an RDP data packet */
108  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  static void
109    rdp_send_data(STREAM s, uint8 data_pdu_type)
110  {  {
         uint16 capset;  
111          uint16 length;          uint16 length;
         BOOL res;  
         int i;  
   
         res = lsb_io_uint32(s, &pdu->shareid);  
   
         if (pdutype == RDP_PDU_CONFIRM_ACTIVE)  
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
   
         res = res ? lsb_io_uint16(s, &pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
   
         if (pdu->source_len > 48)  
         {  
                 ERROR("RDP source descriptor too long\n");  
                 return False;  
         }  
   
         res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
   
         if (s->marshall)  
         {  
                 capset = RDP_CAPSET_GENERAL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_general_caps(s, &pdu->general_caps) : False;  
   
                 capset = RDP_CAPSET_BITMAP;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bitmap_caps (s, &pdu->bitmap_caps ) : False;  
   
                 capset = RDP_CAPSET_ORDER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_order_caps  (s, &pdu->order_caps  ) : False;  
   
                 capset = RDP_CAPSET_BMPCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps) : False;  
   
                 capset = RDP_CAPSET_COLCACHE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_colcache_caps(s, &pdu->colcache_caps) : False;  
   
                 capset = RDP_CAPSET_ACTIVATE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_activate_caps(s, &pdu->activate_caps) : False;  
   
                 capset = RDP_CAPSET_CONTROL;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_control_caps(s, &pdu->control_caps) : False;  
   
                 capset = RDP_CAPSET_POINTER;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_pointer_caps(s, &pdu->pointer_caps) : False;  
   
                 capset = RDP_CAPSET_SHARE;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_share_caps  (s, &pdu->share_caps  ) : False;  
   
                 capset = RDP_CAPSET_UNKNOWN;  
                 res = res ? lsb_io_uint16(s, &capset) : False;  
                 res = res ? rdp_io_unknown_caps(s, NULL) : False;  
         }  
         else  
         {  
                 for (i = 0; i < pdu->num_caps; i++)  
                 {  
                         if (!res)  
                                 return False;  
   
                         if (!lsb_io_uint16(s, &capset))  
                                 return False;  
   
                         switch (capset)  
                         {  
                         case RDP_CAPSET_GENERAL:  
                                 res = rdp_io_general_caps (s, &pdu->general_caps );  
                                 break;  
                         case RDP_CAPSET_BITMAP:  
                                 res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );  
                                 break;  
                         case RDP_CAPSET_ORDER:  
                                 res = rdp_io_order_caps   (s, &pdu->order_caps   );  
                                 break;  
                         case RDP_CAPSET_BMPCACHE:  
                                 res = rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps);  
                                 break;  
                         case RDP_CAPSET_CONTROL:  
                                 res = rdp_io_control_caps (s, &pdu->control_caps );  
                                 break;  
                         case RDP_CAPSET_ACTIVATE:  
                                 res = rdp_io_activate_caps(s, &pdu->activate_caps);  
                                 break;  
                         case RDP_CAPSET_POINTER:  
                                 res = rdp_io_pointer_caps (s, &pdu->pointer_caps );  
                                 break;  
                         case RDP_CAPSET_SHARE:  
                                 res = rdp_io_share_caps   (s, &pdu->share_caps   );  
                                 break;  
                         case RDP_CAPSET_COLCACHE:  
                                 res = rdp_io_colcache_caps(s, &pdu->colcache_caps);  
                                 break;  
                         default:  
                                 NOTIMP("capset 0x%x\n", capset);  
   
                                 if (!lsb_io_uint16(s, &length))  
                                         return False;  
   
                                 s->offset += (length - 4);  
                         }  
                 }  
         }  
   
         return res;  
 }  
   
 /* Construct a control PDU */  
 void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  
 {  
         pdu->action = action;  
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
   
 /* Parse a control PDU */  
 BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  
 {  
         BOOL res = True;  
112    
113          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;          s_pop_layer(s, rdp_hdr);
114          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;          length = s->end - s->p;
         res = res ? lsb_io_uint32(s, &pdu->controlid) : False;  
115    
116          return res;          out_uint16_le(s, length);
117  }          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
118            out_uint16_le(s, (mcs_userid + 1001));
 /* Construct a synchronisation PDU */  
 void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  
 {  
         pdu->type = 1;  
         pdu->userid = userid;  
 }  
   
 /* Parse a synchronisation PDU */  
 BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)  
 {  
         BOOL res = True;  
119    
120          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          out_uint32_le(s, rdp_shareid);
121          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          out_uint8(s, 0);        /* pad */
122            out_uint8(s, 1);        /* streamid */
123            out_uint16(s, (length - 14));
124            out_uint8(s, data_pdu_type);
125            out_uint8(s, 0);        /* compress_type */
126            out_uint16(s, 0);       /* compress_len */
127    
128          return res;          sec_send(s, encryption ? SEC_ENCRYPT : 0);
129  }  }
130    
131  /* Parse a single input event */  /* Output a string in Unicode */
132  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  void
133    rdp_out_unistr(STREAM s, char *string, int len)
134  {  {
135          BOOL res = True;          int i = 0, j = 0;
136    
137          res = res ? lsb_io_uint32(s, &evt->event_time)   : False;          len += 2;
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
         res = res ? lsb_io_uint16(s, &evt->device_flags) : False;  
138    
139          if (!res)          while (i < len)
                 return False;  
   
         switch (evt->message_type)  
140          {          {
141          case RDP_INPUT_CODEPOINT:                  s->p[i++] = string[j++];
142          case RDP_INPUT_VIRTKEY:                  s->p[i++] = 0;
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 break;  
         case RDP_INPUT_SYNCHRONIZE:  
         case RDP_INPUT_SCANCODE:  
         case RDP_INPUT_MOUSE:  
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 res = res ? lsb_io_uint16(s, &evt->param2) : False;  
                 break;  
         default:  
                 NOTIMP("input type %d\n", evt->message_type);  
                 return False;  
143          }          }
144    
145          return res;          s->p += len;
 }  
   
 /* Construct an input PDU */  
 void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  
                         uint16 device_flags, uint16 param1, uint16 param2)  
 {  
         uint32 now = time(NULL);  
   
         pdu->num_events = 1;  
         pdu->pad = 0;  
   
         pdu->event[0].event_time = now;  
         pdu->event[0].message_type = message_type;  
         pdu->event[0].device_flags = device_flags;  
         pdu->event[0].param1 = param1;  
         pdu->event[0].param2 = param2;  
146  }  }
147    
148  /* Parse an input PDU */  /* Parse a logon info packet */
149  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
150    rdp_send_logon_info(uint32 flags, char *domain, char *user,
151                        char *password, char *program, char *directory)
152  {  {
153          BOOL res = True;          int len_domain = 2 * strlen(domain);
154          int i;          int len_user = 2 * strlen(user);
155            int len_password = 2 * strlen(password);
156            int len_program = 2 * strlen(program);
157            int len_directory = 2 * strlen(directory);
158            uint32 sec_flags = 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);
   
         if (pdu->num_events > RDP_MAX_EVENTS)  
         {  
                 ERROR("Too many events in one PDU\n");  
                 return False;  
         }  
163    
164          for (i = 0; i < pdu->num_events; i++)          out_uint32(s, 0);
165          {          out_uint32_le(s, flags);
166                  res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;          out_uint16_le(s, len_domain);
167          }          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          return res;          s_mark_end(s);
178            sec_send(s, sec_flags);
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()
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;  
         }  
   
         for (i = 0; i < pdu->num_fonts; i++)  
         {  
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
         }  
207    
208          return res;          s_mark_end(s);
209            rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
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;
217    
218          res = res ? lsb_io_uint16(s, &ptr->message) : False;          s = rdp_init_data(16);
         res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;  
219    
220          switch (ptr->message)          out_uint16_le(s, 1);    /* number of events */
221          {          out_uint16(s, 0);       /* pad */
                 case RDP_POINTER_MOVE:  
                         res = res ? lsb_io_uint16(s, &ptr->x      ) : False;  
                         res = res ? lsb_io_uint16(s, &ptr->y      ) : False;  
                         break;  
         }  
   
         return res;  
 }  
222    
223  /* Parse an update PDU */          out_uint32_le(s, time);
224  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)          out_uint16_le(s, message_type);
225  {          out_uint16_le(s, device_flags);
226          BOOL res = True;          out_uint16_le(s, param1);
227            out_uint16_le(s, param2);
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
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);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->cx, delta);  
238    
239          if (present & 0x08)          s = rdp_init_data(8);
                 rdp_io_coord(s, &os->cy, delta);  
240    
241          if (present & 0x10)          out_uint16(s, 0);       /* number of fonts */
242                  prs_io_uint8(s, &os->opcode);          out_uint16_le(s, 0x3e); /* unknown */
243            out_uint16_le(s, seq);  /* unknown */
244            out_uint16_le(s, 0x32); /* entry size */
245    
246          return PRS_ERROR(s);          s_mark_end(s);
247            rdp_send_data(s, RDP_DATA_PDU_FONT2);
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);
256    
257          if (present & 0x0002)          out_uint16_le(s, 1);    /* OS major type */
258                  rdp_io_coord(s, &os->y, delta);          out_uint16_le(s, 3);    /* OS minor type */
259            out_uint16_le(s, 0x200);        /* Protocol version */
260          if (present & 0x0004)          out_uint16(s, 0);       /* Pad */
261                  rdp_io_coord(s, &os->cx, delta);          out_uint16(s, 0);       /* Compression types */
262            out_uint16(s, 0);       /* Pad */
263          if (present & 0x0008)          out_uint16(s, 0);       /* Update capability */
264                  rdp_io_coord(s, &os->cy, delta);          out_uint16(s, 0);       /* Remote unshare capability */
265            out_uint16(s, 0);       /* Compression level */
266          if (present & 0x0010)          out_uint16(s, 0);       /* Pad */
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x0040)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         rdp_io_brush(s, &os->brush, present >> 7);  
   
         return PRS_ERROR(s);  
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);  
   
         if (present & 0x0020)  
                 rdp_io_coord(s, &os->srcx, delta);  
275    
276          if (present & 0x0040)          out_uint16_le(s, 8);    /* Preferred BPP */
277                  rdp_io_coord(s, &os->srcy, delta);          out_uint16(s, 1);       /* Receive 1 BPP */
278            out_uint16(s, 1);       /* Receive 4 BPP */
279          return PRS_ERROR(s);          out_uint16_le(s, 1);    /* Receive 8 BPP */
280            out_uint16_le(s, 800);  /* Desktop width */
281            out_uint16_le(s, 600);  /* Desktop height */
282            out_uint16(s, 0);       /* Pad */
283            out_uint16(s, 0);       /* Allow resize */
284            out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */
285            out_uint16(s, 0);       /* Unknown */
286            out_uint16_le(s, 1);    /* Unknown */
287            out_uint16(s, 0);       /* Pad */
288  }  }
289    
290  /* 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);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
295    
         if (present & 0x0040)  
                 prs_io_uint8(s, &os->opcode);  
296    
297          rdp_io_pen(s, &os->pen, present >> 7);          memset(order_caps, 0, 32);
298            order_caps[0] = 1;      /* dest blt */
299            order_caps[1] = 1;      /* pat blt */
300            order_caps[2] = 1;      /* screen blt */
301            order_caps[8] = 1;      /* line */
302            order_caps[9] = 1;      /* line */
303            order_caps[10] = 1;     /* rect */
304            order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */
305            order_caps[13] = 1;     /* memblt */
306            order_caps[14] = 1;     /* triblt */
307            order_caps[22] = 1;     /* polyline */
308            order_caps[27] = 1;     /* text2 */
309            out_uint16_le(s, RDP_CAPSET_ORDER);
310            out_uint16_le(s, RDP_CAPLEN_ORDER);
311    
312          return PRS_ERROR(s);          out_uint8s(s, 20);      /* Terminal desc, pad */
313            out_uint16_le(s, 1);    /* Cache X granularity */
314            out_uint16_le(s, 20);   /* Cache Y granularity */
315            out_uint16(s, 0);       /* Pad */
316            out_uint16_le(s, 1);    /* Max order level */
317            out_uint16_le(s, 0x147);        /* Number of fonts */
318            out_uint16_le(s, 0x2a); /* Capability flags */
319            out_uint8p(s, order_caps, 32);  /* Orders supported */
320            out_uint16_le(s, 0x6a1);        /* Text capability flags */
321            out_uint8s(s, 6);       /* Pad */
322            out_uint32(s, desktop_save == False ? 0 : 0x38400);     /* Desktop cache size */
323            out_uint32(s, 0);       /* Unknown */
324            out_uint32(s, 0x4e4);   /* Unknown */
325  }  }
326    
327  /* Parse an opaque rectangle order */  /* Output bitmap cache capability set */
328  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  static void
329    rdp_out_bmpcache_caps(STREAM s)
330  {  {
331          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
332                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
333    
334          if (present & 0x02)          out_uint8s(s, 24);      /* unused */
335                  rdp_io_coord(s, &os->y, delta);          out_uint16_le(s, 0x258);        /* entries */
336            out_uint16_le(s, 0x100);        /* max cell size */
337          if (present & 0x04)          out_uint16_le(s, 0x12c);        /* entries */
338                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 0x400);        /* max cell size */
339            out_uint16_le(s, 0x106);        /* entries */
340          if (present & 0x08)          out_uint16_le(s, 0x1000);       /* max cell size */
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x10)  
                 prs_io_uint8(s, &os->colour);  
   
         return PRS_ERROR(s);  
341  }  }
342    
343  /* Parse a desktop save order */  /* Output control capability set */
344  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  static void
345    rdp_out_control_caps(STREAM s)
346  {  {
347          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_CONTROL);
348                  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);  
349    
350          if (present & 0x08)          out_uint16(s, 0);       /* Control capabilities */
351                  rdp_io_coord(s, &os->right, delta);          out_uint16(s, 0);       /* Remote detach */
352            out_uint16_le(s, 2);    /* Control interest */
353          if (present & 0x10)          out_uint16_le(s, 2);    /* Detach interest */
                 rdp_io_coord(s, &os->bottom, delta);  
   
         if (present & 0x20)  
                 prs_io_uint8(s, &os->action);  
   
         return PRS_ERROR(s);  
354  }  }
355    
356  /* Parse a memory blt order */  /* Output activation capability set */
357  BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  static void
358    rdp_out_activate_caps(STREAM s)
359  {  {
360          if (present & 0x0001)          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
361          {          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);  
362    
363          if (present & 0x0100)          out_uint16(s, 0);       /* Help key */
364                  lsb_io_uint16(s, &os->cache_idx);          out_uint16(s, 0);       /* Help index key */
365            out_uint16(s, 0);       /* Extended help key */
366          return PRS_ERROR(s);          out_uint16(s, 0);       /* Window activate */
367  }  }
368    
369  /* Parse a 3-way blt order */  /* Output pointer capability set */
370  BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta)  static void
371    rdp_out_pointer_caps(STREAM s)
372  {  {
373          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_POINTER);
374          {          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);  
375    
376          rdp_io_brush(s, &os->brush, present >> 10);          out_uint16(s, 0);       /* Colour pointer */
377            out_uint16_le(s, 20);   /* Cache size */
         if (present & 0x008000)  
                 lsb_io_uint16(s, &os->cache_idx);  
   
         if (present & 0x010000)  
                 lsb_io_uint16(s, &os->unknown);  
   
         return PRS_ERROR(s);  
378  }  }
379    
380  /* Parse a text order */  /* Output share capability set */
381  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  static void
382    rdp_out_share_caps(STREAM s)
383  {  {
384          if (present & 0x000001)          out_uint16_le(s, RDP_CAPSET_SHARE);
385                  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);  
386    
387          if (present & 0x000400)          out_uint16(s, 0);       /* userid */
388                  lsb_io_uint16(s, &os->boxleft);          out_uint16(s, 0);       /* pad */
   
         if (present & 0x000800)  
                 lsb_io_uint16(s, &os->boxtop);  
   
         if (present & 0x001000)  
                 lsb_io_uint16(s, &os->boxright);  
   
         if (present & 0x002000)  
                 lsb_io_uint16(s, &os->boxbottom);  
   
         if (present & 0x080000)  
                 lsb_io_uint16(s, &os->x);  
   
         if (present & 0x100000)  
                 lsb_io_uint16(s, &os->y);  
   
         if (present & 0x200000)  
         {  
                 prs_io_uint8(s, &os->length);  
                 prs_io_uint8s(s, os->text, os->length);  
         }  
   
         return PRS_ERROR(s);  
389  }  }
390    
391    /* Output colour cache capability set */
392  /* SECONDARY ORDERS */  static void
393    rdp_out_colcache_caps(STREAM s)
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
394  {  {
395          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
396            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;  
397    
398          return res;          out_uint16_le(s, 6);    /* cache size */
399            out_uint16(s, 0);       /* pad */
400  }  }
401    
402  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  static uint8 canned_caps[] = {
403  {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
404          BOOL res = True;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
405            0x00, 0x00, 0x00, 0x00, 0x00,
406          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
408          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
410          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;          0x00, 0x00, 0x00, 0x00, 0x00,
412          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413            0x0C, 0x00, 0x08, 0x00, 0x01,
414            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
415            0x10, 0x00, 0x34, 0x00, 0xFE,
416            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
417            0xFE, 0x00, 0x08, 0x00, 0xFE,
418            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
419            0xFE, 0x00, 0x80, 0x00, 0xFE,
420            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
421            0x02, 0x00, 0x00, 0x00
422    };
423    
424          rbo->data = s->data + s->offset;  /* Output unknown capability set */
425          s->offset += rbo->bufsize;  static void
426    rdp_out_unknown_caps(STREAM s)
427    {
428            out_uint16_le(s, RDP_CAPSET_UNKNOWN);
429            out_uint16_le(s, 0x58);
430    
431            out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
432    }
433    
434    /* Send a confirm active PDU */
435    static void
436    rdp_send_confirm_active()
437    {
438            STREAM s;
439            uint16 caplen =
440                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
441                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
442                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
443                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
444    
445            s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));
446    
447            out_uint32_le(s, rdp_shareid);
448            out_uint16_le(s, 0x3ea);        /* userid */
449            out_uint16_le(s, sizeof(RDP_SOURCE));
450            out_uint16_le(s, caplen);
451    
452            out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
453            out_uint16_le(s, 0xd);  /* num_caps */
454            out_uint8s(s, 2);       /* pad */
455    
456            rdp_out_general_caps(s);
457            rdp_out_bitmap_caps(s);
458            rdp_out_order_caps(s);
459            rdp_out_bmpcache_caps(s);
460            rdp_out_colcache_caps(s);
461            rdp_out_activate_caps(s);
462            rdp_out_control_caps(s);
463            rdp_out_pointer_caps(s);
464            rdp_out_share_caps(s);
465            rdp_out_unknown_caps(s);
466    
467            s_mark_end(s);
468            rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);
469    }
470    
471    /* Respond to a demand active PDU */
472    static void
473    process_demand_active(STREAM s)
474    {
475            uint8 type;
476    
477            in_uint32_le(s, rdp_shareid);
478    
479            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));
480    
481            rdp_send_confirm_active();
482            rdp_send_synchronise();
483            rdp_send_control(RDP_CTL_COOPERATE);
484            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
485            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
486            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
487            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
488            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);
489            rdp_send_fonts(1);
490            rdp_send_fonts(2);
491            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
492            reset_order_state();
493    }
494    
495    /* Process a pointer PDU */
496    static void
497    process_pointer_pdu(STREAM s)
498    {
499            uint16 message_type;
500            uint16 x, y, width, height, cache_idx, masklen, datalen;
501            uint8 *mask, *data;
502            HCURSOR cursor;
503    
504          return res;          in_uint16_le(s, message_type);
505  }          in_uint8s(s, 2);        /* pad */
506    
507  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)          switch (message_type)
508  {          {
509          BOOL res = True;                  case RDP_POINTER_MOVE:
510                            in_uint16_le(s, x);
511                            in_uint16_le(s, y);
512                            if (s_check(s))
513                                    ui_move_pointer(x, y);
514                            break;
515    
516          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                  case RDP_POINTER_COLOR:
517          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;                          in_uint16_le(s, cache_idx);
518          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;                          in_uint16_le(s, x);
519          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;                          in_uint16_le(s, y);
520          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;                          in_uint16_le(s, width);
521          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;                          in_uint16_le(s, height);
522          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;                          in_uint16_le(s, masklen);
523          res = res ? lsb_io_uint16(s, &rbo->pad2      ) : False;                          in_uint16_le(s, datalen);
524          res = res ? lsb_io_uint16(s, &rbo->size      ) : False;                          in_uint8p(s, data, datalen);
525          res = res ? lsb_io_uint16(s, &rbo->row_size  ) : False;                          in_uint8p(s, mask, masklen);
526          res = res ? lsb_io_uint16(s, &rbo->final_size) : False;                          cursor = ui_create_cursor(x, y, width, height, mask, data);
527                            ui_set_cursor(cursor);
528                            cache_put_cursor(cache_idx, cursor);
529                            break;
530    
531          rbo->data = s->data + s->offset;                  case RDP_POINTER_CACHED:
532          s->offset += rbo->size;                          in_uint16_le(s, cache_idx);
533                            ui_set_cursor(cache_get_cursor(cache_idx));
534                            break;
535    
536          return res;                  default:
537                            DEBUG(("Pointer message 0x%x\n", message_type));
538            }
539  }  }
540    
541  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process bitmap updates */
542    static void
543    process_bitmap_updates(STREAM s)
544  {  {
545          COLOURENTRY *entry;          uint16 num_updates;
546            uint16 left, top, right, bottom, width, height;
547            uint16 cx, cy, bpp, compress, bufsize, size;
548            uint8 *data, *bmpdata;
549          int i;          int i;
550    
551          prs_io_uint8(s, &colours->cache_id);          in_uint16_le(s, num_updates);
         lsb_io_uint16(s, &colours->map.ncolours);  
552    
553          for (i = 0; i < colours->map.ncolours; i++)          for (i = 0; i < num_updates; i++)
554          {          {
555                  entry = &colours->map.colours[i];                  in_uint16_le(s, left);
556                  prs_io_uint8(s, &entry->blue);                  in_uint16_le(s, top);
557                  prs_io_uint8(s, &entry->green);                  in_uint16_le(s, right);
558                  prs_io_uint8(s, &entry->red);                  in_uint16_le(s, bottom);
559                  s->offset++;                  in_uint16_le(s, width);
560          }                  in_uint16_le(s, height);
561                    in_uint16_le(s, bpp);
562                    in_uint16_le(s, compress);
563                    in_uint16_le(s, bufsize);
564    
565          return True;                  cx = right - left + 1;
566  }                  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;  
567    
568          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",
569          res = res ? prs_io_uint8(s, &font->nglyphs) : False;                         left, top, right, bottom, width, height, compress));
570    
571          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++)  
572                  {                  {
573                          in = glyph->data[j];                          int y;
574                          out = 0;                          bmpdata = xmalloc(width * height);
575                          if (in & 1) out |= 128;                          for (y = 0; y < height; y++)
576                          if (in & 2) out |= 64;                          {
577                          if (in & 4) out |= 32;                                  in_uint8a(s, &bmpdata[(height - y - 1) * width], width);
578                          if (in & 8) out |= 16;                          }
579                          if (in & 16) out |= 8;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
580                          if (in & 32) out |= 4;                          xfree(bmpdata);
581                          if (in & 64) out |= 2;                          continue;
                         if (in & 128) out |= 1;  
                         glyph->data[j] = out;  
582                  }                  }
         }  
   
         return res;  
 }  
   
   
 /* CAPABILITIES */  
   
 /* Construct a general capability set */  
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
   
 /* Parse general capability set */  
 BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_GENERAL;  
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_types) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_update    ) : False;  
         res = res ? lsb_io_uint16(s, &caps->remote_unshare) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_level) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3          ) : False;  
   
         return res;  
 }  
   
 /* Construct a bitmap capability set */  
 void rdp_make_bitmap_caps(RDP_BITMAP_CAPS *caps, int width, int height)  
 {  
         caps->preferred_bpp = 8;  
         caps->receive1bpp = 1;  
         caps->receive4bpp = 1;  
         caps->receive8bpp = 1;  
         caps->width = width;  
         caps->height = height;  
         caps->compression = 1;  
         caps->unknown2 = 1;  
 }  
   
 /* Parse bitmap capability set */  
 BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BITMAP;  
         uint16 pkt_length = length;  
         BOOL res;  
583    
584          res = lsb_io_uint16(s, &pkt_length);                  in_uint8s(s, 2);        /* pad */
585          if (pkt_length != length)                  in_uint16_le(s, size);
586          {                  in_uint8s(s, 4);        /* line_size, final_size */
587                  ERROR("Unrecognised capabilities size\n");                  in_uint8p(s, data, size);
                 return False;  
         }  
588    
589          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  bmpdata = xmalloc(width * height);
590          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;                  if (bitmap_decompress(bmpdata, width, height, data, size))
591          res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;                  {
592          res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
593          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;  
594    
595          res = lsb_io_uint16(s, &pkt_length);                  xfree(bmpdata);
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
596          }          }
   
         res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;  
         res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;  
         res = res ? lsb_io_uint16(s, &caps->xgranularity     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ygranularity     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2             ) : False;  
         res = res ? lsb_io_uint16(s, &caps->max_order_level  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->num_fonts        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_flags        ) : False;  
         res = res ? prs_io_uint8s(s,  caps->support      , 32) : False;  
         res = res ? lsb_io_uint16(s, &caps->text_cap_flags   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->pad4             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->desk_save_size   ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown1         ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown2         ) : False;  
   
         return res;  
 }  
   
 /* Construct a bitmap cache capability set */  
 void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  
 {  
         caps->caches[0].entries = 0x258;  
         caps->caches[0].max_cell_size = 0x100;  
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
597  }  }
598    
599  /* Parse single bitmap cache information structure */  /* Process a palette update */
600  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  static void
601    process_palette(STREAM s)
602  {  {
603          if (!lsb_io_uint16(s, &info->entries      ))          HCOLOURMAP hmap;
604                  return False;          COLOURMAP map;
605            uint8 *colours;
606    
607          if (!lsb_io_uint16(s, &info->max_cell_size))          in_uint8s(s, 2);        /* pad */
608                  return False;          in_uint16_le(s, map.ncolours);
609            in_uint8s(s, 2);        /* pad */
610            in_uint8p(s, colours, (map.ncolours * 3));
611            map.colours = (COLOURENTRY *) colours;
612    
613          return True;          hmap = ui_create_colourmap(&map);
614            ui_set_colourmap(hmap);
615  }  }
616    
617  /* Parse bitmap cache capability set */  /* Process an update PDU */
618  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  static void
619    process_update_pdu(STREAM s)
620  {  {
621          uint16 length = RDP_CAPLEN_BMPCACHE;          uint16 update_type;
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
622    
623          for (i = 0; i < 6; i++)          in_uint16_le(s, update_type);
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
624    
625          for (i = 0; i < 3; i++)          switch (update_type)
626                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;          {
627                    case RDP_UPDATE_ORDERS:
628                            process_orders(s);
629                            break;
630    
631          return res;                  case RDP_UPDATE_BITMAP:
632  }                          process_bitmap_updates(s);
633                            break;
634    
635  /* Construct a control capability set */                  case RDP_UPDATE_PALETTE:
636  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)                          process_palette(s);
637  {                          break;
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
638    
639  /* Parse control capability set */                  case RDP_UPDATE_SYNCHRONIZE:
640  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)                          break;
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
641    
642          res = lsb_io_uint16(s, &pkt_length);                  default:
643          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
644          }          }
645    
         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;  
646  }  }
647    
648  /* Construct an activation capability set */  /* Process data PDU */
649  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  static void
650    process_data_pdu(STREAM s)
651  {  {
652  }          uint8 data_pdu_type;
653    
654  /* Parse activation capability set */          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
655  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)          in_uint8(s, data_pdu_type);
656  {          in_uint8s(s, 3);        /* compress_type, compress_len */
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
657    
658          res = lsb_io_uint16(s, &pkt_length);          switch (data_pdu_type)
         if (pkt_length != length)  
659          {          {
660                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
661                  return False;                          process_update_pdu(s);
662          }                          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;  
663    
664          return res;                  case RDP_DATA_PDU_POINTER:
665  }                          process_pointer_pdu(s);
666                            break;
667    
668  /* Construct a pointer capability set */                  case RDP_DATA_PDU_BELL:
669  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)                          ui_bell();
670  {                          break;
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
671    
672  /* Parse pointer capability set */                  case RDP_DATA_PDU_LOGON:
673  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)                          /* User logged on */
674  {                          break;
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
675    
676          res = lsb_io_uint16(s, &pkt_length);                  default:
677          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
678          }          }
   
         res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;  
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
   
         return res;  
679  }  }
680    
681  /* Construct a share capability set */  /* Process incoming packets */
682  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  void
683    rdp_main_loop()
684  {  {
685  }          uint8 type;
686            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;  
687    
688          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
689          {          {
690                  ERROR("Unrecognised capabilities size\n");                  switch (type)
691                  return False;                  {
692          }                          case RDP_PDU_DEMAND_ACTIVE:
693                                    process_demand_active(s);
694                                    break;
695    
696          res = res ? lsb_io_uint16(s, &caps->userid) : False;                          case RDP_PDU_DEACTIVATE:
697          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                                  break;
698    
699          return res;                          case RDP_PDU_DATA:
700  }                                  process_data_pdu(s);
701                                    break;
702    
703  /* Construct a colour cache capability set */                          default:
704  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)                                  unimpl("PDU %d\n", type);
705  {                  }
706          caps->cache_size = 6;          }
707  }  }
708    
709  /* Parse colour cache capability set */  /* Establish a connection up to the RDP layer */
710  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
711    rdp_connect(char *server, uint32 flags, char *domain, char *password,
712                char *command, char *directory)
713  {  {
714          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");  
715                  return False;                  return False;
         }  
716    
717          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          rdp_send_logon_info(flags, domain, username, password, command, directory);
718          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          return True;
   
         return res;  
719  }  }
720    
721  uint8 canned_caps[] = {  /* Disconnect from the RDP layer */
722  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  void
723  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  rdp_disconnect()
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x01,  
 0x00,0x00,0x00,0x0E,0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x34,0x00,0xFE,  
 0x00,0x04,0x00,0xFE,0x00,0x04,0x00,0xFE,0x00,0x08,0x00,0xFE,0x00,0x08,0x00,0xFE,  
 0x00,0x10,0x00,0xFE,0x00,0x20,0x00,0xFE,0x00,0x40,0x00,0xFE,0x00,0x80,0x00,0xFE,  
 0x00,0x00,0x01,0x40,0x00,0x00,0x08,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00  
 };  
   
 /* Insert canned capabilities */  
 BOOL rdp_io_unknown_caps(STREAM s, void *caps)  
724  {  {
725          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;  
726  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26