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

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

  ViewVC Help
Powered by ViewVC 1.1.26