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

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

  ViewVC Help
Powered by ViewVC 1.1.26