/[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 678 by jsorg71, Mon Apr 26 22:31:22 2004 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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
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 <time.h>
22    #include "rdesktop.h"
 /* Establish a connection up to the RDP layer */  
 HCONN rdp_connect(char *server, int width, int height)  
 {  
         HCONN conn;  
   
         if ((conn = mcs_connect(server)) == NULL)  
                 return NULL;  
23    
24          rdp_establish_key(conn);  extern uint16 g_mcs_userid;
25          mcs_recv(conn, False); /* Server's licensing certificate */  extern char g_username[16];
26          rdp_send_cert(conn);  extern BOOL g_bitmap_compression;
27          mcs_recv(conn, False);  extern BOOL g_orders;
28          mcs_recv(conn, False);  extern BOOL g_encryption;
29    extern BOOL g_desktop_save;
30    extern BOOL g_use_rdp5;
31    extern uint16 g_server_rdp_version;
32    extern uint32 g_rdp5_performanceflags;
33    extern int g_server_bpp;
34    extern int g_width;
35    extern int g_height;
36    extern BOOL g_bitmap_cache;
37    
38          return conn;  uint8 *g_next_packet;
39    uint32 g_rdp_shareid;
 }  
   
 /* 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  
 };  
40    
41  uint8 precanned_key_packet_e2[] = {  #if WITH_DEBUG
42  0x48,0x00,0x00,0x00,0x8a,0xe4,0x9f,0x8a,0xd5,0x04,0x02,0xfd,0x09,0x1f,0xff,0x53,  static uint32 g_packetno;
43  0xe0,0xb2,0x72,0x8b,0x19,0xba,0x22,0xe4,0x2a,0x7b,0xeb,0x79,0xa8,0x83,0x31,0x6f,  #endif
 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);  
 }  
44    
45  /* Initialise RDP transport packet */  /* Receive an RDP packet */
46  void rdp_init(HCONN conn)  static STREAM
47    rdp_recv(uint8 * type)
48  {  {
49          mcs_init_data(conn);          static STREAM rdp_s;
50          PUSH_LAYER(conn->out, rdp_offset, 6);          uint16 length, pdu_type;
 }  
51    
52  /* Transmit RDP transport packet */          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
53  void rdp_send(HCONN conn, uint16 pdu_type)          {
54  {                  rdp_s = sec_recv();
55          RDP_HEADER hdr;                  if (rdp_s == NULL)
56          int length;                          return NULL;
57    
58          POP_LAYER(conn->out, rdp_offset);                  g_next_packet = rdp_s->p;
59          length = conn->out.end - conn->out.offset;          }
60          rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);          else
61          rdp_io_header(&conn->out, &hdr);          {
62          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);                  rdp_s->p = g_next_packet;
63  }          }
64    
65  /* Initialise RDP transport data packet */          in_uint16_le(rdp_s, length);
66  void rdp_init_data(HCONN conn)          /* 32k packets are really 8, keepalive fix */
67  {          if (length == 0x8000)
68          mcs_init_data(conn);          {
69          PUSH_LAYER(conn->out, rdp_offset, 18);                  g_next_packet += 8;
70  }                  *type = 0;
71                    return rdp_s;
72            }
73            in_uint16_le(rdp_s, pdu_type);
74            in_uint8s(rdp_s, 2);    /* userid */
75            *type = pdu_type & 0xf;
76    
77  /* Transmit RDP transport data packet */  #if WITH_DEBUG
78  void rdp_send_data(HCONN conn, uint16 data_pdu_type)          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
79  {          hexdump(g_next_packet, length);
80          RDP_HEADER hdr;  #endif /*  */
         RDP_DATA_HEADER datahdr;  
         int length = conn->out.end - conn->out.offset;  
81    
82          POP_LAYER(conn->out, rdp_offset);          g_next_packet += length;
83          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);  
84  }  }
85    
86  void rdp_send_confirm_active(HCONN conn, uint32 shareid, int width, int height)  /* Initialise an RDP data packet */
87    static STREAM
88    rdp_init_data(int maxlen)
89  {  {
90          RDP_ACTIVE_PDU active;          STREAM s;
91    
92          rdp_init(conn);          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
93          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;  
94    
95          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);  
96  }  }
97    
98  void rdp_send_control(HCONN conn, uint16 action)  /* Send an RDP data packet */
99    static void
100    rdp_send_data(STREAM s, uint8 data_pdu_type)
101  {  {
102          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);  
 }  
103    
104  void rdp_send_fonts(HCONN conn, uint16 seqno)          s_pop_layer(s, rdp_hdr);
105  {          length = s->end - s->p;
         RDP_FONT_PDU fonts;  
106    
107          rdp_init_data(conn);          out_uint16_le(s, length);
108          rdp_make_font_pdu(&fonts, seqno);          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
109          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);  
 }  
110    
111  void rdp_send_input(HCONN conn, uint16 message_type, uint16 device_flags,          out_uint32_le(s, g_rdp_shareid);
112                                  uint16 param1, uint16 param2)          out_uint8(s, 0);        /* pad */
113  {          out_uint8(s, 1);        /* streamid */
114          RDP_INPUT_PDU input;          out_uint16_le(s, (length - 14));
115            out_uint8(s, data_pdu_type);
116            out_uint8(s, 0);        /* compress_type */
117            out_uint16(s, 0);       /* compress_len */
118    
119          rdp_init_data(conn);          sec_send(s, g_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);  
120  }  }
121    
122  BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  /* Output a string in Unicode */
123    void
124    rdp_out_unistr(STREAM s, char *string, int len)
125  {  {
126          RDP_HEADER hdr;          int i = 0, j = 0;
127    
128          conn->in.offset = conn->in.rdp_offset;          len += 2;
129    
130          if (conn->in.offset >= conn->in.end)          while (i < len)
131          {          {
132                  if (!mcs_recv(conn, False))                  s->p[i++] = string[j++];
133                          return False;                  s->p[i++] = 0;
134          }          }
135    
136          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;  
137  }  }
138    
139  /* Disconnect from the RDP layer */  /* Input a string in Unicode
140  void rdp_disconnect(HCONN conn)   *
141  {   * Returns str_len of string
142          mcs_disconnect(conn);   */
143  }  int
144    rdp_in_unistr(STREAM s, char *string, int uni_len)
 /* 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)  
145  {  {
146          BOOL res = True;          int i = 0;
   
         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;  
147    
148          return res;          while (i < uni_len / 2)
149  }          {
150                    in_uint8a(s, &string[i++], 1);
151                    in_uint8s(s, 1);
152            }
153    
154  /* Construct a data header */          return i - 1;
 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;  
155  }  }
156    
 /* 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;  
 }  
157    
158  BOOL rdp_io_present(STREAM s, uint32 *present, uint8 flags, int size)  /* Parse a logon info packet */
159    static void
160    rdp_send_logon_info(uint32 flags, char *domain, char *user,
161                        char *password, char *program, char *directory)
162  {  {
163          uint8 bits;          char *ipaddr = tcp_get_address();
164          int i;          int len_domain = 2 * strlen(domain);
165            int len_user = 2 * strlen(user);
166          if (flags & RDP_ORDER_SMALL)          int len_password = 2 * strlen(password);
167          {          int len_program = 2 * strlen(program);
168                  size--;          int len_directory = 2 * strlen(directory);
169          }          int len_ip = 2 * strlen(ipaddr);
170            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
171          if (flags & RDP_ORDER_TINY)          int packetlen = 0;
172          {          uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
173                  if (size < 2)          STREAM s;
174                          return False;          time_t t = time(NULL);
175            time_t tzone;
176    
177                  size -= 2;  #if 0
178          }          // enable rdp compression
179            flags |= RDP_COMPRESSION;
180    #endif
181    
182          *present = 0;          if (!g_use_rdp5 || 1 == g_server_rdp_version)
         for (i = 0; i < size; i++)  
183          {          {
184                  prs_io_uint8(s, &bits);                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
                 *present |= bits << (i * 8);  
         }  
   
         return True;  
 }  
185    
186  BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)                  s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
187  {                               + len_program + len_directory + 10);
         uint8 change;  
         BOOL res;  
188    
189          if (delta)                  out_uint32(s, 0);
190          {                  out_uint32_le(s, flags);
191                  res = prs_io_uint8(s, &change);                  out_uint16_le(s, len_domain);
192                  *coord += (char)change;                  out_uint16_le(s, len_user);
193                    out_uint16_le(s, len_password);
194                    out_uint16_le(s, len_program);
195                    out_uint16_le(s, len_directory);
196                    rdp_out_unistr(s, domain, len_domain);
197                    rdp_out_unistr(s, user, len_user);
198                    rdp_out_unistr(s, password, len_password);
199                    rdp_out_unistr(s, program, len_program);
200                    rdp_out_unistr(s, directory, len_directory);
201          }          }
202          else          else
203          {          {
204                  res = lsb_io_uint16(s, coord);                  flags |= RDP_LOGON_BLOB;
205          }                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
206                    packetlen = 4 + /* Unknown uint32 */
207          return res;                          4 +     /* flags */
208  }                          2 +     /* len_domain */
209                            2 +     /* len_user */
210  BOOL rdp_io_colour(STREAM s, uint8 *colour)                          (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
211  {                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
212          BOOL res;                          2 +     /* len_program */
213                            2 +     /* len_directory */
214          res = prs_io_uint8(s, colour);                          (0 < len_domain ? len_domain : 2) +     /* domain */
215          s->offset += 2;                          len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
216                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
217                            (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
218                            2 +     /* Client ip length */
219                            len_ip +        /* Client ip */
220                            2 +     /* DLL string length */
221                            len_dll +       /* DLL string */
222                            2 +     /* Unknown */
223                            2 +     /* Unknown */
224                            64 +    /* Time zone #0 */
225                            2 +     /* Unknown */
226                            64 +    /* Time zone #1 */
227                            32;     /* Unknown */
228    
229                    s = sec_init(sec_flags, packetlen);
230                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
231    
232                    out_uint32(s, 0);       /* Unknown */
233                    out_uint32_le(s, flags);
234                    out_uint16_le(s, len_domain);
235                    out_uint16_le(s, len_user);
236                    if (flags & RDP_LOGON_AUTO)
237                    {
238                            out_uint16_le(s, len_password);
239    
240          return res;                  }
241  }                  if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
242                    {
243                            out_uint16_le(s, 0);
244                    }
245                    out_uint16_le(s, len_program);
246                    out_uint16_le(s, len_directory);
247                    if (0 < len_domain)
248                            rdp_out_unistr(s, domain, len_domain);
249                    else
250                            out_uint16_le(s, 0);
251                    rdp_out_unistr(s, user, len_user);
252                    if (flags & RDP_LOGON_AUTO)
253                    {
254                            rdp_out_unistr(s, password, len_password);
255                    }
256                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
257                    {
258                            out_uint16_le(s, 0);
259                    }
260                    if (0 < len_program)
261                    {
262                            rdp_out_unistr(s, program, len_program);
263    
264  BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours)                  }
265  {                  else
266          int datasize;                  {
267                            out_uint16_le(s, 0);
268                    }
269                    if (0 < len_directory)
270                    {
271                            rdp_out_unistr(s, directory, len_directory);
272                    }
273                    else
274                    {
275                            out_uint16_le(s, 0);
276                    }
277                    out_uint16_le(s, 2);
278                    out_uint16_le(s, len_ip + 2);   /* Length of client ip */
279                    rdp_out_unistr(s, ipaddr, len_ip);
280                    out_uint16_le(s, len_dll + 2);
281                    rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
282    
283          lsb_io_uint16(s, &colours->ncolours);                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
284          datasize = colours->ncolours * 3;                  out_uint32_le(s, tzone);
285    
286          if (datasize > sizeof(colours->colours))                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
287                  return False;                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
288    
289          memcpy(colours->colours, s->data + s->offset, datasize);                  out_uint32_le(s, 0x0a0000);
290          s->offset += datasize;                  out_uint32_le(s, 0x050000);
291          return True;                  out_uint32_le(s, 3);
292  }                  out_uint32_le(s, 0);
293                    out_uint32_le(s, 0);
294    
295  BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds)                  rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
296  {                  out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
         uint8 present;  
297    
298          prs_io_uint8(s, &present);                  out_uint32_le(s, 0x30000);
299                    out_uint32_le(s, 0x050000);
300                    out_uint32_le(s, 2);
301                    out_uint32(s, 0);
302                    out_uint32_le(s, 0xffffffc4);
303                    out_uint32_le(s, 0xfffffffe);
304                    out_uint32_le(s, g_rdp5_performanceflags);
305                    out_uint32(s, 0);
306    
         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);  
307    
308          return True;          }
309            s_mark_end(s);
310            sec_send(s, sec_flags);
311  }  }
312    
313  BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present)  /* Send a control PDU */
314    static void
315    rdp_send_control(uint16 action)
316  {  {
317          BOOL res = True;          STREAM s;
318    
319          if (present & 1)          s = rdp_init_data(8);
                 res = res ? prs_io_uint8(s, &pen->style) : False;  
320    
321          if (present & 2)          out_uint16_le(s, action);
322                  res = res ? prs_io_uint8(s, &pen->width) : False;          out_uint16(s, 0);       /* userid */
323            out_uint32(s, 0);       /* control id */
324    
325          if (present & 4)          s_mark_end(s);
326                  res = res ? rdp_io_colour(s, &pen->colour) : False;          rdp_send_data(s, RDP_DATA_PDU_CONTROL);
   
         return res;  
327  }  }
328    
329  BOOL rdp_io_brush(STREAM s, BRUSH *brush, uint32 present)  /* Send a synchronisation PDU */
330    static void
331    rdp_send_synchronise(void)
332  {  {
333          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;  
   
         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;  
334    
335          return res;          s = rdp_init_data(4);
 }  
   
 /* 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));  
336    
337          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          out_uint16_le(s, 1);    /* type */
338                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          out_uint16_le(s, 1002);
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
339    
340          rdp_make_general_caps (&pdu->general_caps );          s_mark_end(s);
341          rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);          rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
         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);  
342  }  }
343    
344  /* Parse a confirm/demand active PDU */  /* Send a single input event */
345  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  void
346    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
347  {  {
348          uint16 capset;          STREAM s;
         uint16 length;  
         BOOL res;  
         int i;  
   
         res = lsb_io_uint32(s, &pdu->shareid);  
349    
350          if (pdutype == RDP_PDU_CONFIRM_ACTIVE)          s = rdp_init_data(16);
                 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);  
351    
352                                  if (!lsb_io_uint16(s, &length))          out_uint16_le(s, 1);    /* number of events */
353                                          return False;          out_uint16(s, 0);       /* pad */
354    
355                                  s->offset += (length - 4);          out_uint32_le(s, time);
356                          }          out_uint16_le(s, message_type);
357                  }          out_uint16_le(s, device_flags);
358          }          out_uint16_le(s, param1);
359            out_uint16_le(s, param2);
360    
361          return res;          s_mark_end(s);
362            rdp_send_data(s, RDP_DATA_PDU_INPUT);
363  }  }
364    
365  /* Construct a control PDU */  /* Send an (empty) font information PDU */
366  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  static void
367    rdp_send_fonts(uint16 seq)
368  {  {
369          pdu->action = action;          STREAM s;
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
370    
371  /* Parse a control PDU */          s = rdp_init_data(8);
 BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  
 {  
         BOOL res = True;  
372    
373          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;          out_uint16(s, 0);       /* number of fonts */
374          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;          out_uint16_le(s, 0);    /* pad? */
375          res = res ? lsb_io_uint32(s, &pdu->controlid) : False;          out_uint16_le(s, seq);  /* unknown */
376            out_uint16_le(s, 0x32); /* entry size */
377    
378          return res;          s_mark_end(s);
379            rdp_send_data(s, RDP_DATA_PDU_FONT2);
380  }  }
381    
382  /* Construct a synchronisation PDU */  /* Output general capability set */
383  void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  static void
384    rdp_out_general_caps(STREAM s)
385  {  {
386          pdu->type = 1;          out_uint16_le(s, RDP_CAPSET_GENERAL);
387          pdu->userid = userid;          out_uint16_le(s, RDP_CAPLEN_GENERAL);
388    
389            out_uint16_le(s, 1);    /* OS major type */
390            out_uint16_le(s, 3);    /* OS minor type */
391            out_uint16_le(s, 0x200);        /* Protocol version */
392            out_uint16(s, 0);       /* Pad */
393            out_uint16(s, 0);       /* Compression types */
394            out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
395            /* Pad, according to T.128. 0x40d seems to
396               trigger
397               the server to start sending RDP5 packets.
398               However, the value is 0x1d04 with W2KTSK and
399               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
400               for sending such information in a padding
401               field.. */
402            out_uint16(s, 0);       /* Update capability */
403            out_uint16(s, 0);       /* Remote unshare capability */
404            out_uint16(s, 0);       /* Compression level */
405            out_uint16(s, 0);       /* Pad */
406  }  }
407    
408  /* Parse a synchronisation PDU */  /* Output bitmap capability set */
409  BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)  static void
410    rdp_out_bitmap_caps(STREAM s)
411  {  {
412          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_BITMAP);
413            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;  
414    
415          return res;          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
416            out_uint16_le(s, 1);    /* Receive 1 BPP */
417            out_uint16_le(s, 1);    /* Receive 4 BPP */
418            out_uint16_le(s, 1);    /* Receive 8 BPP */
419            out_uint16_le(s, 800);  /* Desktop width */
420            out_uint16_le(s, 600);  /* Desktop height */
421            out_uint16(s, 0);       /* Pad */
422            out_uint16(s, 1);       /* Allow resize */
423            out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
424            out_uint16(s, 0);       /* Unknown */
425            out_uint16_le(s, 1);    /* Unknown */
426            out_uint16(s, 0);       /* Pad */
427  }  }
428    
429  /* Parse a single input event */  /* Output order capability set */
430  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  static void
431    rdp_out_order_caps(STREAM s)
432  {  {
433          BOOL res = True;          uint8 order_caps[32];
   
         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;  
434    
         if (!res)  
                 return False;  
435    
436          switch (evt->message_type)          memset(order_caps, 0, 32);
437          {          order_caps[0] = 1;      /* dest blt */
438          case RDP_INPUT_CODEPOINT:          order_caps[1] = 1;      /* pat blt */
439          case RDP_INPUT_VIRTKEY:          order_caps[2] = 1;      /* screen blt */
440                  res = res ? lsb_io_uint16(s, &evt->param1) : False;          order_caps[3] = (g_bitmap_cache ? 1 : 0); /* memblt */
441                  break;          order_caps[8] = 1;      /* line */
442          case RDP_INPUT_SYNCHRONIZE:          order_caps[9] = 1;      /* line */
443          case RDP_INPUT_SCANCODE:          order_caps[10] = 1;     /* rect */
444          case RDP_INPUT_MOUSE:          order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */
445                  res = res ? lsb_io_uint16(s, &evt->param1) : False;          order_caps[13] = 1;     /* memblt */
446                  res = res ? lsb_io_uint16(s, &evt->param2) : False;          order_caps[14] = 1;     /* triblt */
447                  break;          order_caps[22] = 1;     /* polyline */
448          default:          order_caps[27] = 1;     /* text2 */
449                  NOTIMP("input type %d\n", evt->message_type);          out_uint16_le(s, RDP_CAPSET_ORDER);
450                  return False;          out_uint16_le(s, RDP_CAPLEN_ORDER);
         }  
451    
452          return res;          out_uint8s(s, 20);      /* Terminal desc, pad */
453            out_uint16_le(s, 1);    /* Cache X granularity */
454            out_uint16_le(s, 20);   /* Cache Y granularity */
455            out_uint16(s, 0);       /* Pad */
456            out_uint16_le(s, 1);    /* Max order level */
457            out_uint16_le(s, 0x147);        /* Number of fonts */
458            out_uint16_le(s, 0x2a); /* Capability flags */
459            out_uint8p(s, order_caps, 32);  /* Orders supported */
460            out_uint16_le(s, 0x6a1);        /* Text capability flags */
461            out_uint8s(s, 6);       /* Pad */
462            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
463            out_uint32(s, 0);       /* Unknown */
464            out_uint32_le(s, 0x4e4);        /* Unknown */
465  }  }
466    
467  /* Construct an input PDU */  /* Output bitmap cache capability set */
468  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  static void
469                          uint16 device_flags, uint16 param1, uint16 param2)  rdp_out_bmpcache_caps(STREAM s)
470  {  {
471          uint32 now = time(NULL);          int Bpp;
472            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
473          pdu->num_events = 1;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
         pdu->pad = 0;  
474    
475          pdu->event[0].event_time = now;          Bpp = (g_server_bpp + 7) / 8;
476          pdu->event[0].message_type = message_type;          out_uint8s(s, 24);      /* unused */
477          pdu->event[0].device_flags = device_flags;          out_uint16_le(s, 0x258);        /* entries */
478          pdu->event[0].param1 = param1;          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
479          pdu->event[0].param2 = param2;          out_uint16_le(s, 0x12c);        /* entries */
480            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
481            out_uint16_le(s, 0x106);        /* entries */
482            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
483  }  }
484    
485  /* Parse an input PDU */  /* Output control capability set */
486  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
487    rdp_out_control_caps(STREAM s)
488  {  {
489          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_CONTROL);
490          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;  
         }  
   
         for (i = 0; i < pdu->num_events; i++)  
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
         }  
   
         return res;  
 }  
491    
492  /* Construct a font information PDU */          out_uint16(s, 0);       /* Control capabilities */
493  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          out_uint16(s, 0);       /* Remote detach */
494  {          out_uint16_le(s, 2);    /* Control interest */
495          pdu->num_fonts = 0;          out_uint16_le(s, 2);    /* Detach interest */
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
496  }  }
497    
498  /* Parse a font information structure */  /* Output activation capability set */
499  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  static void
500    rdp_out_activate_caps(STREAM s)
501  {  {
502          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
503            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
         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;  
504    
505          return res;          out_uint16(s, 0);       /* Help key */
506            out_uint16(s, 0);       /* Help index key */
507            out_uint16(s, 0);       /* Extended help key */
508            out_uint16(s, 0);       /* Window activate */
509  }  }
510    
511  /* Parse a font information PDU */  /* Output pointer capability set */
512  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  static void
513    rdp_out_pointer_caps(STREAM s)
514  {  {
515          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_POINTER);
516          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;  
         }  
517    
518          return res;          out_uint16(s, 0);       /* Colour pointer */
519            out_uint16_le(s, 20);   /* Cache size */
520  }  }
521    
522  /* Parse a pointer PDU */  /* Output share capability set */
523  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  static void
524    rdp_out_share_caps(STREAM s)
525  {  {
526          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_SHARE);
527            out_uint16_le(s, RDP_CAPLEN_SHARE);
528    
529          res = res ? lsb_io_uint16(s, &ptr->message) : False;          out_uint16(s, 0);       /* userid */
530          res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;          out_uint16(s, 0);       /* pad */
   
         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;  
         }  
   
         return res;  
531  }  }
532    
533  /* Parse an update PDU */  /* Output colour cache capability set */
534  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  static void
535    rdp_out_colcache_caps(STREAM s)
536  {  {
537          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
538            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
539    
540          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;          out_uint16_le(s, 6);    /* cache size */
541          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;          out_uint16(s, 0);       /* pad */
   
         return res;  
542  }  }
543    
544    static uint8 canned_caps[] = {
545            0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
546            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
547            0x00, 0x00, 0x00, 0x00, 0x00,
548            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
549            0x00, 0x00, 0x00, 0x00, 0x00,
550            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
551            0x00, 0x00, 0x00, 0x00, 0x00,
552            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
553            0x00, 0x00, 0x00, 0x00, 0x00,
554            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
555            0x0C, 0x00, 0x08, 0x00, 0x01,
556            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
557            0x10, 0x00, 0x34, 0x00, 0xFE,
558            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
559            0xFE, 0x00, 0x08, 0x00, 0xFE,
560            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
561            0xFE, 0x00, 0x80, 0x00, 0xFE,
562            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
563            0x02, 0x00, 0x00, 0x00
564    };
565    
566  /* PRIMARY ORDERS */  /* Output unknown capability sets (number 13, 12, 14 and 16) */
567    static void
568  /* 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)  
569  {  {
570          if (present & 0x01)          out_uint16_le(s, RDP_CAPSET_UNKNOWN);
571                  rdp_io_coord(s, &os->x, delta);          out_uint16_le(s, 0x58);
   
         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);  
572    
573          if (present & 0x10)          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
                 prs_io_uint8(s, &os->opcode);  
   
         return PRS_ERROR(s);  
574  }  }
575    
576  /* Parse an pattern blt order */  #define RDP5_FLAG 0x0030
577  BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  /* Send a confirm active PDU */
578    static void
579    rdp_send_confirm_active(void)
580  {  {
581          if (present & 0x0001)          STREAM s;
582                  rdp_io_coord(s, &os->x, delta);          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
583            uint16 caplen =
584          if (present & 0x0002)                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
585                  rdp_io_coord(s, &os->y, delta);                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
586                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
587          if (present & 0x0004)                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
                 rdp_io_coord(s, &os->cx, delta);  
588    
589          if (present & 0x0008)          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
                 rdp_io_coord(s, &os->cy, delta);  
590    
591          if (present & 0x0010)          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
592                  prs_io_uint8(s, &os->opcode);          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
593            out_uint16_le(s, (g_mcs_userid + 1001));
594    
595          if (present & 0x0020)          out_uint32_le(s, g_rdp_shareid);
596                  rdp_io_colour(s, &os->bgcolour);          out_uint16_le(s, 0x3ea);        /* userid */
597            out_uint16_le(s, sizeof(RDP_SOURCE));
598            out_uint16_le(s, caplen);
599    
600          if (present & 0x0040)          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
601                  rdp_io_colour(s, &os->fgcolour);          out_uint16_le(s, 0xd);  /* num_caps */
602            out_uint8s(s, 2);       /* pad */
603    
604          rdp_io_brush(s, &os->brush, present >> 7);          rdp_out_general_caps(s);
605            rdp_out_bitmap_caps(s);
606            rdp_out_order_caps(s);
607            rdp_out_bmpcache_caps(s);
608            rdp_out_colcache_caps(s);
609            rdp_out_activate_caps(s);
610            rdp_out_control_caps(s);
611            rdp_out_pointer_caps(s);
612            rdp_out_share_caps(s);
613            rdp_out_unknown_caps(s);
614    
615          return PRS_ERROR(s);          s_mark_end(s);
616            sec_send(s, sec_flags);
617  }  }
618    
619  /* Parse an screen blt order */  /* Process a general capability set */
620  BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  static void
621    rdp_process_general_caps(STREAM s)
622  {  {
623          if (present & 0x0001)          uint16 pad2octetsB;     /* rdp5 flags? */
                 rdp_io_coord(s, &os->x, delta);  
   
         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);  
624    
625          if (present & 0x0010)          in_uint8s(s, 10);
626                  prs_io_uint8(s, &os->opcode);          in_uint16_le(s, pad2octetsB);
627    
628          if (present & 0x0020)          if (!pad2octetsB)
629                  rdp_io_coord(s, &os->srcx, delta);                  g_use_rdp5 = False;
   
         if (present & 0x0040)  
                 rdp_io_coord(s, &os->srcy, delta);  
   
         return PRS_ERROR(s);  
630  }  }
631    
632  /* Parse a line order */  /* Process a bitmap capability set */
633  BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  static void
634    rdp_process_bitmap_caps(STREAM s)
635  {  {
636          if (present & 0x0001)          uint16 width, height, bpp;
                 lsb_io_uint16(s, &os->mixmode);  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->startx, delta);  
637    
638          if (present & 0x0004)          in_uint16_le(s, bpp);
639                  rdp_io_coord(s, &os->starty, delta);          in_uint8s(s, 6);
640    
641          if (present & 0x0008)          in_uint16_le(s, width);
642                  rdp_io_coord(s, &os->endx, delta);          in_uint16_le(s, height);
643    
644          if (present & 0x0010)          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
                 rdp_io_coord(s, &os->endy, delta);  
645    
646          if (present & 0x0020)          /*
647                  rdp_io_colour(s, &os->bgcolour);           * The server may limit bpp and change the size of the desktop (for
648             * example when shadowing another session).
649             */
650            g_server_bpp = bpp;
651            g_width = width;
652            g_height = height;
653    
654          if (present & 0x0040)          ui_resize_window();
                 prs_io_uint8(s, &os->opcode);  
   
         rdp_io_pen(s, &os->pen, present >> 7);  
   
         return PRS_ERROR(s);  
655  }  }
656    
657  /* Parse an opaque rectangle order */  /* Respond to a demand active PDU */
658  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  static void
659    process_demand_active(STREAM s)
660  {  {
661          if (present & 0x01)          int n;
662                  rdp_io_coord(s, &os->x, delta);          uint8 type, *next;
663            uint16 len_src_descriptor, len_combined_caps, num_capsets, capset_type, capset_length;
         if (present & 0x02)  
                 rdp_io_coord(s, &os->y, delta);  
664    
665          if (present & 0x04)          in_uint32_le(s, g_rdp_shareid);
666                  rdp_io_coord(s, &os->cx, delta);          in_uint16_le(s, len_src_descriptor);
667            in_uint16_le(s, len_combined_caps);
668            in_uint8s(s, len_src_descriptor);
669    
670          if (present & 0x08)          in_uint16_le(s, num_capsets);
671                  rdp_io_coord(s, &os->cy, delta);          in_uint8s(s, 2);        /* pad */
672    
673          if (present & 0x10)          DEBUG(("DEMAND_ACTIVE(id=0x%x,num_caps=%d)\n", g_rdp_shareid, num_capsets));
                 prs_io_uint8(s, &os->colour);  
674    
675          return PRS_ERROR(s);          for (n = 0; n < num_capsets; n++)
676  }          {
677                    in_uint16_le(s, capset_type);
678  /* Parse a desktop save order */                  in_uint16_le(s, capset_length);
 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);  
679    
680          if (present & 0x04)                  next = s->p + capset_length - 4;
                 rdp_io_coord(s, &os->top, delta);  
681    
682          if (present & 0x08)                  switch (capset_type)
683                  rdp_io_coord(s, &os->right, delta);                  {
684                            case RDP_CAPSET_GENERAL:
685                                    rdp_process_general_caps(s);
686                                    break;
687    
688          if (present & 0x10)                          case RDP_CAPSET_BITMAP:
689                  rdp_io_coord(s, &os->bottom, delta);                                  rdp_process_bitmap_caps(s);
690                                    break;
691                    }
692    
693          if (present & 0x20)                  s->p = next;
694                  prs_io_uint8(s, &os->action);          }
695    
696          return PRS_ERROR(s);          rdp_send_confirm_active();
697  }          rdp_send_synchronise();
698            rdp_send_control(RDP_CTL_COOPERATE);
699            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
700            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
701            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
702            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
703            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
704    
705  /* Parse a memory blt order */          if (g_use_rdp5)
 BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
706          {          {
707                  prs_io_uint8(s, &os->cache_id);                  rdp_send_fonts(3);
                 prs_io_uint8(s, &os->colour_table);  
708          }          }
709            else
         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);  
   
         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)  
710          {          {
711                  prs_io_uint8(s, &os->cache_id);                  rdp_send_fonts(1);
712                  prs_io_uint8(s, &os->colour_table);                  rdp_send_fonts(2);
713          }          }
714    
715          if (present & 0x000002)          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
716                  rdp_io_coord(s, &os->x, delta);          reset_order_state();
   
         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);  
717  }  }
718    
719  /* Parse a text order */  /* Process a colour pointer PDU */
720  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  void
721    process_colour_pointer_pdu(STREAM s)
722  {  {
723          if (present & 0x000001)          uint16 x, y, width, height, cache_idx, masklen, datalen;
724                  prs_io_uint8(s, &os->font);          uint8 *mask, *data;
725            HCURSOR cursor;
         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);  
726    
727          if (present & 0x000400)          in_uint16_le(s, cache_idx);
728                  lsb_io_uint16(s, &os->boxleft);          in_uint16_le(s, x);
729            in_uint16_le(s, y);
730          if (present & 0x000800)          in_uint16_le(s, width);
731                  lsb_io_uint16(s, &os->boxtop);          in_uint16_le(s, height);
732            in_uint16_le(s, masklen);
733          if (present & 0x001000)          in_uint16_le(s, datalen);
734                  lsb_io_uint16(s, &os->boxright);          in_uint8p(s, data, datalen);
735            in_uint8p(s, mask, masklen);
736          if (present & 0x002000)          cursor = ui_create_cursor(x, y, width, height, mask, data);
737                  lsb_io_uint16(s, &os->boxbottom);          ui_set_cursor(cursor);
738            cache_put_cursor(cache_idx, cursor);
         if (present & 0x080000)  
                 lsb_io_uint16(s, &os->x);  
   
         if (present & 0x100000)  
                 lsb_io_uint16(s, &os->y);  
   
         if (present & 0x200000)  
         {  
                 prs_io_uint8(s, &os->length);  
                 prs_io_uint8s(s, os->text, os->length);  
         }  
   
         return PRS_ERROR(s);  
739  }  }
740    
741    /* Process a cached pointer PDU */
742    void
743    process_cached_pointer_pdu(STREAM s)
744    {
745            uint16 cache_idx;
746    
747  /* SECONDARY ORDERS */          in_uint16_le(s, cache_idx);
748            ui_set_cursor(cache_get_cursor(cache_idx));
749    }
750    
751  BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  /* Process a system pointer PDU */
752    void
753    process_system_pointer_pdu(STREAM s)
754  {  {
755          BOOL res = True;          uint16 system_pointer_type;
756    
757          res = res ? lsb_io_uint16(s, &rso->length) : False;          in_uint16(s, system_pointer_type);
758          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          switch (system_pointer_type)
759          res = res ? prs_io_uint8 (s, &rso->type  ) : False;          {
760                    case RDP_NULL_POINTER:
761                            ui_set_null_cursor();
762                            break;
763    
764          return res;                  default:
765                            unimpl("System pointer message 0x%x\n", system_pointer_type);
766            }
767  }  }
768    
769  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  /* Process a pointer PDU */
770    static void
771    process_pointer_pdu(STREAM s)
772  {  {
773          BOOL res = True;          uint16 message_type;
774            uint16 x, y;
         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;  
775    
776          rbo->data = s->data + s->offset;          in_uint16_le(s, message_type);
777          s->offset += rbo->bufsize;          in_uint8s(s, 2);        /* pad */
778    
779          return res;          switch (message_type)
780  }          {
781                    case RDP_POINTER_MOVE:
782                            in_uint16_le(s, x);
783                            in_uint16_le(s, y);
784                            if (s_check(s))
785                                    ui_move_pointer(x, y);
786                            break;
787    
788  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)                  case RDP_POINTER_COLOR:
789  {                          process_colour_pointer_pdu(s);
790          BOOL res = True;                          break;
791    
792          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                  case RDP_POINTER_CACHED:
793          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;                          process_cached_pointer_pdu(s);
794          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;  
795    
796          rbo->data = s->data + s->offset;                  case RDP_POINTER_SYSTEM:
797          s->offset += rbo->size;                          process_system_pointer_pdu(s);
798                            break;
799    
800          return res;                  default:
801                            unimpl("Pointer message 0x%x\n", message_type);
802            }
803  }  }
804    
805  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process bitmap updates */
806    void
807    process_bitmap_updates(STREAM s)
808  {  {
809          COLOURENTRY *entry;          uint16 num_updates;
810            uint16 left, top, right, bottom, width, height;
811            uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
812            uint8 *data, *bmpdata;
813          int i;          int i;
814    
815          prs_io_uint8(s, &colours->cache_id);          in_uint16_le(s, num_updates);
         lsb_io_uint16(s, &colours->map.ncolours);  
816    
817          for (i = 0; i < colours->map.ncolours; i++)          for (i = 0; i < num_updates; i++)
818          {          {
819                  entry = &colours->map.colours[i];                  in_uint16_le(s, left);
820                  prs_io_uint8(s, &entry->blue);                  in_uint16_le(s, top);
821                  prs_io_uint8(s, &entry->green);                  in_uint16_le(s, right);
822                  prs_io_uint8(s, &entry->red);                  in_uint16_le(s, bottom);
823                  s->offset++;                  in_uint16_le(s, width);
824          }                  in_uint16_le(s, height);
825                    in_uint16_le(s, bpp);
826          return True;                  Bpp = (bpp + 7) / 8;
827  }                  in_uint16_le(s, compress);
828                    in_uint16_le(s, bufsize);
829    
830  BOOL rdp_io_fontcache_order(STREAM s, RDP_FONTCACHE_ORDER *font)                  cx = right - left + 1;
831  {                  cy = bottom - top + 1;
         RDP_FONT_GLYPH *glyph;  
         BOOL res = True;  
         int i, j, datasize;  
         uint8 in, out;  
832    
833          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",
834          res = res ? prs_io_uint8(s, &font->nglyphs) : False;                         left, top, right, bottom, width, height, Bpp, compress));
835    
836          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++)  
837                  {                  {
838                          in = glyph->data[j];                          int y;
839                          out = 0;                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
840                          if (in & 1) out |= 128;                          for (y = 0; y < height; y++)
841                          if (in & 2) out |= 64;                          {
842                          if (in & 4) out |= 32;                                  in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
843                          if (in & 8) out |= 16;                                            width * Bpp);
844                          if (in & 16) out |= 8;                          }
845                          if (in & 32) out |= 4;                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
846                          if (in & 64) out |= 2;                          xfree(bmpdata);
847                          if (in & 128) out |= 1;                          continue;
                         glyph->data[j] = out;  
848                  }                  }
         }  
   
         return res;  
 }  
849    
850    
851  /* CAPABILITIES */                  if (compress & 0x400)
852                    {
853                            size = bufsize;
854                    }
855                    else
856                    {
857                            in_uint8s(s, 2);        /* pad */
858                            in_uint16_le(s, size);
859                            in_uint8s(s, 4);        /* line_size, final_size */
860                    }
861                    in_uint8p(s, data, size);
862                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
863                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
864                    {
865                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
866                    }
867                    else
868                    {
869                            DEBUG_RDP5(("Failed to decompress data\n"));
870                    }
871    
872  /* Construct a general capability set */                  xfree(bmpdata);
873  void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)          }
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
874  }  }
875    
876  /* Parse general capability set */  /* Process a palette update */
877  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  void
878    process_palette(STREAM s)
879  {  {
880          uint16 length = RDP_CAPLEN_GENERAL;          COLOURENTRY *entry;
881          uint16 pkt_length = length;          COLOURMAP map;
882          BOOL res;          HCOLOURMAP hmap;
883            int i;
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
884    
885          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          in_uint8s(s, 2);        /* pad */
886          res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;          in_uint16_le(s, map.ncolours);
887          res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;          in_uint8s(s, 2);        /* pad */
         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;  
888    
889          res = lsb_io_uint16(s, &pkt_length);          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
890    
891          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
         res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->width        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->height       ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->allow_resize ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compression  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown1     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown2     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2         ) : False;  
   
         return res;  
 }  
   
 /* Construct an order capability set */  
 void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  
 {  
         caps->xgranularity = 1;  
         caps->ygranularity = 20;  
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
   
 //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;  
   
         caps->support[0] = caps->support[1] = caps->support[2]  
                 = caps->support[3] = caps->support[4] = caps->support[5]  
                 = caps->support[6] = caps->support[8] = caps->support[11]  
                 = caps->support[12] = caps->support[22] = caps->support[28]  
                 = caps->support[29] = caps->support[30] = 1;  
         caps->text_cap_flags = 0x6A1;  
         caps->desk_save_size = 0x38400;  
         caps->unknown2 = 0x4E4;  
 }  
   
 /* Parse order capability set */  
 BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_ORDER;  
         uint16 pkt_length = length;  
         BOOL res;  
892    
893          res = lsb_io_uint16(s, &pkt_length);          for (i = 0; i < map.ncolours; i++)
         if (pkt_length != length)  
894          {          {
895                  ERROR("Unrecognised capabilities size\n");                  entry = &map.colours[i];
896                  return False;                  in_uint8(s, entry->red);
897                    in_uint8(s, entry->green);
898                    in_uint8(s, entry->blue);
899          }          }
900    
901          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;          hmap = ui_create_colourmap(&map);
902          res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;          ui_set_colourmap(hmap);
903          res = res ? lsb_io_uint16(s, &caps->xgranularity     ) : False;  
904          res = res ? lsb_io_uint16(s, &caps->ygranularity     ) : False;          xfree(map.colours);
         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;  
905  }  }
906    
907  /* Parse single bitmap cache information structure */  /* Process an update PDU */
908  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  static void
909    process_update_pdu(STREAM s)
910  {  {
911          if (!lsb_io_uint16(s, &info->entries      ))          uint16 update_type, count;
                 return False;  
912    
913          if (!lsb_io_uint16(s, &info->max_cell_size))          in_uint16_le(s, update_type);
                 return False;  
914    
915          return True;          switch (update_type)
916  }          {
917                    case RDP_UPDATE_ORDERS:
918                            in_uint8s(s, 2);        /* pad */
919                            in_uint16_le(s, count);
920                            in_uint8s(s, 2);        /* pad */
921                            process_orders(s, count);
922                            break;
923    
924  /* Parse bitmap cache capability set */                  case RDP_UPDATE_BITMAP:
925  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)                          process_bitmap_updates(s);
926  {                          break;
         uint16 length = RDP_CAPLEN_BMPCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
927    
928          res = lsb_io_uint16(s, &pkt_length);                  case RDP_UPDATE_PALETTE:
929          if (pkt_length != length)                          process_palette(s);
930          {                          break;
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
931    
932          for (i = 0; i < 6; i++)                  case RDP_UPDATE_SYNCHRONIZE:
933                  res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;                          break;
934    
935          for (i = 0; i < 3; i++)                  default:
936                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;                          unimpl("update %d\n", update_type);
937            }
938    
         return res;  
939  }  }
940    
941  /* Construct a control capability set */  /* Process a disconnect PDU */
942  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)  void
943    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
944  {  {
945          caps->control_interest = 2;          in_uint32_le(s, *ext_disc_reason);
946          caps->detach_interest = 2;  
947            DEBUG(("Received disconnect PDU\n"));
948  }  }
949    
950  /* Parse control capability set */  /* Process data PDU */
951  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  static BOOL
952    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
953  {  {
954          uint16 length = RDP_CAPLEN_CONTROL;          uint8 data_pdu_type;
955          uint16 pkt_length = length;          uint8 ctype;
956          BOOL res;          uint16 clen;
957            int len;
958    #if 0
959            int roff, rlen, ret;
960            static struct stream ns;
961            static signed char *dict = 0;
962    #endif
963    
964            in_uint8s(s, 6);        /* shareid, pad, streamid */
965            in_uint16(s, len);
966            in_uint8(s, data_pdu_type);
967            in_uint8(s, ctype);
968            in_uint16(s, clen);
969            clen -= 18;
970    
971          res = lsb_io_uint16(s, &pkt_length);  #if 0
972          if (pkt_length != length)          if (ctype & 0x20)
973          {          {
974                  ERROR("Unrecognised capabilities size\n");                  if (!dict)
975                  return False;                  {
976          }                          dict = (signed char *) malloc(8200 * sizeof(signed char));
977                            dict = (signed char *) memset(dict, 0, 8200 * sizeof(signed char));
978                    }
979    
980          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;                  ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen);
         res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->control_interest) : False;  
         res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  
981    
982          return res;                  len -= 18;
 }  
983    
984  /* Construct an activation capability set */                  ns.data = xrealloc(ns.data, len);
 void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)  
 {  
 }  
985    
986  /* Parse activation capability set */                  ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len);
 BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
987    
988          res = lsb_io_uint16(s, &pkt_length);                  ns.size = len;
989          if (pkt_length != length)                  ns.end = ns.data + ns.size;
990          {                  ns.p = ns.data;
991                  ERROR("Unrecognised capabilities size\n");                  ns.rdp_hdr = ns.p;
992                  return False;  
993                    s = &ns;
994          }          }
995    #endif
996    
997          res = res ? lsb_io_uint16(s, &caps->help_key         ) : False;          switch (data_pdu_type)
998          res = res ? lsb_io_uint16(s, &caps->help_index_key   ) : False;          {
999          res = res ? lsb_io_uint16(s, &caps->help_extended_key) : False;                  case RDP_DATA_PDU_UPDATE:
1000          res = res ? lsb_io_uint16(s, &caps->window_activate  ) : False;                          process_update_pdu(s);
1001                            break;
1002    
1003          return res;                  case RDP_DATA_PDU_CONTROL:
1004  }                          DEBUG(("Received Control PDU\n"));
1005                            break;
1006    
1007  /* Construct a pointer capability set */                  case RDP_DATA_PDU_SYNCHRONISE:
1008  void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)                          DEBUG(("Received Sync PDU\n"));
1009  {                          break;
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
 }  
1010    
1011  /* Parse pointer capability set */                  case RDP_DATA_PDU_POINTER:
1012  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)                          process_pointer_pdu(s);
1013  {                          break;
         uint16 length = RDP_CAPLEN_POINTER;  
         uint16 pkt_length = length;  
         BOOL res;  
1014    
1015          res = lsb_io_uint16(s, &pkt_length);                  case RDP_DATA_PDU_BELL:
1016          if (pkt_length != length)                          ui_bell();
1017          {                          break;
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
1018    
1019          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_DATA_PDU_LOGON:
1020          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          DEBUG(("Received Logon PDU\n"));
1021                            /* User logged on */
1022                            break;
1023    
1024          return res;                  case RDP_DATA_PDU_DISCONNECT:
1025  }                          process_disconnect_pdu(s, ext_disc_reason);
1026                            return True;
1027    
1028  /* Construct a share capability set */                  default:
1029  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)                          unimpl("data PDU %d\n", data_pdu_type);
1030  {          }
1031            return False;
1032  }  }
1033    
1034  /* Parse share capability set */  /* Process incoming packets */
1035  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)  void
1036    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1037  {  {
1038          uint16 length = RDP_CAPLEN_SHARE;          uint8 type;
1039          uint16 pkt_length = length;          BOOL disc = False;      /* True when a disconnect PDU was received */
1040          BOOL res;          STREAM s;
1041    
1042          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
1043          {          {
1044                  ERROR("Unrecognised capabilities size\n");                  switch (type)
1045                  return False;                  {
1046          }                          case RDP_PDU_DEMAND_ACTIVE:
1047                                    process_demand_active(s);
1048                                    *deactivated = False;
1049                                    break;
1050    
1051          res = res ? lsb_io_uint16(s, &caps->userid) : False;                          case RDP_PDU_DEACTIVATE:
1052          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1053                                    *deactivated = True;
1054                                    break;
1055    
1056          return res;                          case RDP_PDU_DATA:
1057  }                                  disc = process_data_pdu(s, ext_disc_reason);
1058                                    break;
1059    
1060  /* Construct a colour cache capability set */                          case 0:
1061  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)                                  break;
 {  
         caps->cache_size = 6;  
 }  
1062    
1063  /* Parse colour cache capability set */                          default:
1064  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)                                  unimpl("PDU %d\n", type);
1065  {                  }
         uint16 length = RDP_CAPLEN_COLCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
1066    
1067          res = lsb_io_uint16(s, &pkt_length);                  if (disc)
1068          if (pkt_length != length)                  {
1069          {                          return;
1070                  ERROR("Unrecognised capabilities size\n");                  }
                 return False;  
1071          }          }
1072            return;
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
   
         return res;  
1073  }  }
1074    
1075  uint8 canned_caps[] = {  /* Establish a connection up to the RDP layer */
1076  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  BOOL
1077  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,
1078  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)  
1079  {  {
1080          uint16 length = 0x58;          if (!sec_connect(server, g_username))
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
1081                  return False;                  return False;
         }  
1082    
1083          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1084            return True;
1085    }
1086    
1087          return res;  /* Disconnect from the RDP layer */
1088    void
1089    rdp_disconnect(void)
1090    {
1091            sec_disconnect();
1092  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26