/[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 192 by matthewc, Tue Sep 24 07:59:14 2002 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Protocol services - RDP layer     Protocol services - RDP layer
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2001
5        
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include "includes.h"  #include "rdesktop.h"
22    
23  /* Establish a connection up to the RDP layer */  extern uint16 mcs_userid;
24  HCONN rdp_connect(char *server, 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_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          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(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;  
         }  
   
         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_le(s, 1);    /* Receive 1 BPP */
278            out_uint16_le(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[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          return PRS_ERROR(s);          out_uint8s(s, 20);      /* Terminal desc, pad */
314            out_uint16_le(s, 1);    /* Cache X granularity */
315            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);
334    
335          if (present & 0x02)          out_uint8s(s, 24);      /* unused */
336                  rdp_io_coord(s, &os->y, delta);          out_uint16_le(s, 0x258);        /* entries */
337            out_uint16_le(s, 0x100);        /* max cell size */
338          if (present & 0x04)          out_uint16_le(s, 0x12c);        /* entries */
339                  rdp_io_coord(s, &os->cx, delta);          out_uint16_le(s, 0x400);        /* max cell size */
340            out_uint16_le(s, 0x106);        /* entries */
341          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);  
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);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->top, delta);  
350    
351          if (present & 0x08)          out_uint16(s, 0);       /* Control capabilities */
352                  rdp_io_coord(s, &os->right, delta);          out_uint16(s, 0);       /* Remote detach */
353            out_uint16_le(s, 2);    /* Control interest */
354          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);  
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);  
   
         if (present & 0x0080)  
                 rdp_io_coord(s, &os->srcy, delta);  
363    
364          if (present & 0x0100)          out_uint16(s, 0);       /* Help key */
365                  lsb_io_uint16(s, &os->cache_idx);          out_uint16(s, 0);       /* Help index key */
366            out_uint16(s, 0);       /* Extended help key */
367          return PRS_ERROR(s);          out_uint16(s, 0);       /* Window activate */
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);  
   
         if (present & 0x000200)  
                 rdp_io_colour(s, &os->fgcolour);  
376    
377          rdp_io_brush(s, &os->brush, present >> 10);          out_uint16(s, 0);       /* Colour pointer */
378            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);  
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);  
   
         if (present & 0x000200)  
                 lsb_io_uint16(s, &os->clipbottom);  
387    
388          if (present & 0x000400)          out_uint16(s, 0);       /* userid */
389                  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);  
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);
         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;  
398    
399          return res;          out_uint16_le(s, 6);    /* cache size */
400            out_uint16(s, 0);       /* pad */
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                    in_uint16_le(s, compress);
564                    in_uint16_le(s, bufsize);
565    
566          return True;                  cx = right - left + 1;
567  }                  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;  
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;  
 }  
   
   
 /* 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;  
584    
585          res = lsb_io_uint16(s, &pkt_length);                  in_uint8s(s, 2);        /* pad */
586          if (pkt_length != length)                  in_uint16_le(s, size);
587          {                  in_uint8s(s, 4);        /* line_size, final_size */
588                  ERROR("Unrecognised capabilities size\n");                  in_uint8p(s, data, size);
                 return False;  
         }  
589    
590          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  bmpdata = xmalloc(width * height);
591          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;                  if (bitmap_decompress(bmpdata, width, height, data, size))
592          res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;                  {
593          res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
594          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;  
595    
596          res = lsb_io_uint16(s, &pkt_length);                  xfree(bmpdata);
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
597          }          }
   
         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;  
598  }  }
599    
600  /* Parse single bitmap cache information structure */  /* Process a palette update */
601  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  static void
602    process_palette(STREAM s)
603  {  {
604          if (!lsb_io_uint16(s, &info->entries      ))          HCOLOURMAP hmap;
605                  return False;          COLOURMAP map;
606            uint8 *colours;
607    
608          if (!lsb_io_uint16(s, &info->max_cell_size))          in_uint8s(s, 2);        /* pad */
609                  return False;          in_uint16_le(s, map.ncolours);
610            in_uint8s(s, 2);        /* pad */
611            in_uint8p(s, colours, (map.ncolours * 3));
612            map.colours = (COLOURENTRY *) colours;
613    
614          return True;          hmap = ui_create_colourmap(&map);
615            ui_set_colourmap(hmap);
616  }  }
617    
618  /* Parse bitmap cache capability set */  /* Process an update PDU */
619  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  static void
620    process_update_pdu(STREAM s)
621  {  {
622          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;  
         }  
623    
624          for (i = 0; i < 6; i++)          in_uint16_le(s, update_type);
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
625    
626          for (i = 0; i < 3; i++)          switch (update_type)
627                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;          {
628                    case RDP_UPDATE_ORDERS:
629                            process_orders(s);
630                            break;
631    
632          return res;                  case RDP_UPDATE_BITMAP:
633  }                          process_bitmap_updates(s);
634                            break;
635    
636  /* Construct a control capability set */                  case RDP_UPDATE_PALETTE:
637  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)                          process_palette(s);
638  {                          break;
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
639    
640  /* Parse control capability set */                  case RDP_UPDATE_SYNCHRONIZE:
641  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)                          break;
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
642    
643          res = lsb_io_uint16(s, &pkt_length);                  default:
644          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
645          }          }
646    
         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;  
647  }  }
648    
649  /* Construct an activation capability set */  /* Process data PDU */
650  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  static void
651    process_data_pdu(STREAM s)
652  {  {
653  }          uint8 data_pdu_type;
654    
655  /* Parse activation capability set */          in_uint8s(s, 8);        /* shareid, pad, streamid, length */
656  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)          in_uint8(s, data_pdu_type);
657  {          in_uint8s(s, 3);        /* compress_type, compress_len */
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
658    
659          res = lsb_io_uint16(s, &pkt_length);          switch (data_pdu_type)
         if (pkt_length != length)  
660          {          {
661                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
662                  return False;                          process_update_pdu(s);
663          }                          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;  
664    
665          return res;                  case RDP_DATA_PDU_POINTER:
666  }                          process_pointer_pdu(s);
667                            break;
668    
669  /* Construct a pointer capability set */                  case RDP_DATA_PDU_BELL:
670  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)                          ui_bell();
671  {                          break;
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
672    
673  /* Parse pointer capability set */                  case RDP_DATA_PDU_LOGON:
674  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)                          /* User logged on */
675  {                          break;
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
676    
677          res = lsb_io_uint16(s, &pkt_length);                  default:
678          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
679          }          }
   
         res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;  
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
   
         return res;  
680  }  }
681    
682  /* Construct a share capability set */  /* Process incoming packets */
683  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)  void
684    rdp_main_loop(void)
685  {  {
686  }          uint8 type;
687            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;  
688    
689          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
690          {          {
691                  ERROR("Unrecognised capabilities size\n");                  switch (type)
692                  return False;                  {
693          }                          case RDP_PDU_DEMAND_ACTIVE:
694                                    process_demand_active(s);
695                                    break;
696    
697          res = res ? lsb_io_uint16(s, &caps->userid) : False;                          case RDP_PDU_DEACTIVATE:
698          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                                  break;
699    
700          return res;                          case RDP_PDU_DATA:
701  }                                  process_data_pdu(s);
702                                    break;
703    
704  /* Construct a colour cache capability set */                          default:
705  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)                                  unimpl("PDU %d\n", type);
706  {                  }
707          caps->cache_size = 6;          }
708  }  }
709    
710  /* Parse colour cache capability set */  /* Establish a connection up to the RDP layer */
711  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
712    rdp_connect(char *server, uint32 flags, char *domain, char *password,
713                char *command, char *directory)
714  {  {
715          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");  
716                  return False;                  return False;
         }  
717    
718          res = res ? lsb_io_uint16(s, &caps->cache_size) : False;          rdp_send_logon_info(flags, domain, username, password, command, directory);
719          res = res ? lsb_io_uint16(s, &caps->pad       ) : False;          return True;
   
         return res;  
720  }  }
721    
722  uint8 canned_caps[] = {  /* Disconnect from the RDP layer */
723  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  void
724  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)  
725  {  {
726          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;  
727  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26