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

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

  ViewVC Help
Powered by ViewVC 1.1.26