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

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

  ViewVC Help
Powered by ViewVC 1.1.26