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

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

  ViewVC Help
Powered by ViewVC 1.1.26