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

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

  ViewVC Help
Powered by ViewVC 1.1.26