/[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 830 by jdmeijer, Tue Mar 8 00:23:02 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    
         res = res ? lsb_io_uint32(s, &evt->event_time)   : False;  
         res = res ? lsb_io_uint16(s, &evt->message_type) : False;  
         res = res ? lsb_io_uint16(s, &evt->device_flags) : False;  
498    
499          if (!res)          memset(order_caps, 0, 32);
500                  return False;          order_caps[0] = 1;      /* dest blt */
501            order_caps[1] = 1;      /* pat blt */
502            order_caps[2] = 1;      /* screen blt */
503            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
504            order_caps[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[22] = 1;     /* polyline */
511            order_caps[27] = 1;     /* text2 */
512            out_uint16_le(s, RDP_CAPSET_ORDER);
513            out_uint16_le(s, RDP_CAPLEN_ORDER);
514    
515          switch (evt->message_type)          out_uint8s(s, 20);      /* Terminal desc, pad */
516          {          out_uint16_le(s, 1);    /* Cache X granularity */
517          case RDP_INPUT_CODEPOINT:          out_uint16_le(s, 20);   /* Cache Y granularity */
518          case RDP_INPUT_VIRTKEY:          out_uint16(s, 0);       /* Pad */
519                  res = res ? lsb_io_uint16(s, &evt->param1) : False;          out_uint16_le(s, 1);    /* Max order level */
520                  break;          out_uint16_le(s, 0x147);        /* Number of fonts */
521          case RDP_INPUT_SYNCHRONIZE:          out_uint16_le(s, 0x2a); /* Capability flags */
522          case RDP_INPUT_SCANCODE:          out_uint8p(s, order_caps, 32);  /* Orders supported */
523          case RDP_INPUT_MOUSE:          out_uint16_le(s, 0x6a1);        /* Text capability flags */
524                  res = res ? lsb_io_uint16(s, &evt->param1) : False;          out_uint8s(s, 6);       /* Pad */
525                  res = res ? lsb_io_uint16(s, &evt->param2) : False;          out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
526                  break;          out_uint32(s, 0);       /* Unknown */
527          default:          out_uint32_le(s, 0x4e4);        /* Unknown */
                 NOTIMP("input type %d\n", evt->message_type);  
                 return False;  
         }  
   
         return res;  
528  }  }
529    
530  /* Construct an input PDU */  /* Output bitmap cache capability set */
531  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  static void
532                          uint16 device_flags, uint16 param1, uint16 param2)  rdp_out_bmpcache_caps(STREAM s)
533  {  {
534          uint32 now = time(NULL);          int Bpp;
535            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
536          pdu->num_events = 1;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
         pdu->pad = 0;  
537    
538          pdu->event[0].event_time = now;          Bpp = (g_server_bpp + 7) / 8;
539          pdu->event[0].message_type = message_type;          out_uint8s(s, 24);      /* unused */
540          pdu->event[0].device_flags = device_flags;          out_uint16_le(s, 0x258);        /* entries */
541          pdu->event[0].param1 = param1;          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
542          pdu->event[0].param2 = param2;          out_uint16_le(s, 0x12c);        /* entries */
543            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
544            out_uint16_le(s, 0x106);        /* entries */
545            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
546  }  }
547    
548  /* Parse an input PDU */  /* Output bitmap cache v2 capability set */
549  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
550    rdp_out_bmpcache2_caps(STREAM s)
551  {  {
552          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
553          int i;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
554    
555            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
556    
557          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;  
558    
559          if (pdu->num_events > RDP_MAX_EVENTS)          out_uint32_le(s, BMPCACHE2_C0_CELLS);
560            out_uint32_le(s, BMPCACHE2_C1_CELLS);
561            if (pstcache_init(2))
562          {          {
563                  ERROR("Too many events in one PDU\n");                  out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
                 return False;  
564          }          }
565            else
         for (i = 0; i < pdu->num_events; i++)  
566          {          {
567                  res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;                  out_uint32_le(s, BMPCACHE2_C2_CELLS);
568          }          }
569            out_uint8s(s, 20);      /* other bitmap caches not used */
         return res;  
570  }  }
571    
572  /* Construct a font information PDU */  /* Output control capability set */
573  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)  static void
574    rdp_out_control_caps(STREAM s)
575  {  {
576          pdu->num_fonts = 0;          out_uint16_le(s, RDP_CAPSET_CONTROL);
577          pdu->unknown1 = 0x3e;          out_uint16_le(s, RDP_CAPLEN_CONTROL);
578          pdu->unknown2 = seqno;  
579          pdu->entry_size = RDP_FONT_INFO_SIZE;          out_uint16(s, 0);       /* Control capabilities */
580            out_uint16(s, 0);       /* Remote detach */
581            out_uint16_le(s, 2);    /* Control interest */
582            out_uint16_le(s, 2);    /* Detach interest */
583  }  }
584    
585  /* Parse a font information structure */  /* Output activation capability set */
586  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  static void
587    rdp_out_activate_caps(STREAM s)
588  {  {
589          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
590            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
         res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;  
         res = res ? lsb_io_uint16(s, &font->flags    ) : False;  
         res = res ? lsb_io_uint16(s, &font->width    ) : False;  
         res = res ? lsb_io_uint16(s, &font->height   ) : False;  
         res = res ? lsb_io_uint16(s, &font->xaspect  ) : False;  
         res = res ? lsb_io_uint16(s, &font->yaspect  ) : False;  
         res = res ? lsb_io_uint32(s, &font->signature) : False;  
         res = res ? lsb_io_uint16(s, &font->codepage ) : False;  
         res = res ? lsb_io_uint16(s, &font->ascent   ) : False;  
591    
592          return res;          out_uint16(s, 0);       /* Help key */
593            out_uint16(s, 0);       /* Help index key */
594            out_uint16(s, 0);       /* Extended help key */
595            out_uint16(s, 0);       /* Window activate */
596  }  }
597    
598  /* Parse a font information PDU */  /* Output pointer capability set */
599  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  static void
600    rdp_out_pointer_caps(STREAM s)
601  {  {
602          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_POINTER);
603          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;  
         }  
604    
605          for (i = 0; i < pdu->num_fonts; i++)          out_uint16(s, 0);       /* Colour pointer */
606          {          out_uint16_le(s, 20);   /* Cache size */
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
         }  
   
         return res;  
607  }  }
608    
609  /* Parse a pointer PDU */  /* Output share capability set */
610  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  static void
611    rdp_out_share_caps(STREAM s)
612  {  {
613          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_SHARE);
614            out_uint16_le(s, RDP_CAPLEN_SHARE);
615    
616          res = res ? lsb_io_uint16(s, &ptr->message) : False;          out_uint16(s, 0);       /* userid */
617          res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;          out_uint16(s, 0);       /* pad */
   
         switch (ptr->message)  
         {  
                 case RDP_POINTER_MOVE:  
                         res = res ? lsb_io_uint16(s, &ptr->x      ) : False;  
                         res = res ? lsb_io_uint16(s, &ptr->y      ) : False;  
                         break;  
         }  
   
         return res;  
618  }  }
619    
620  /* Parse an update PDU */  /* Output colour cache capability set */
621  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  static void
622    rdp_out_colcache_caps(STREAM s)
623  {  {
624          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
625            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
626    
627          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;          out_uint16_le(s, 6);    /* cache size */
628          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;          out_uint16(s, 0);       /* pad */
   
         return res;  
629  }  }
630    
631    static uint8 caps_0x0d[] = {
632            0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
633            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634            0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638            0x00, 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
643    };
644    
645  /* 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);  
646    
647          if (present & 0x04)  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
                 rdp_io_coord(s, &os->cx, delta);  
648    
649          if (present & 0x08)  static uint8 caps_0x10[] = {
650                  rdp_io_coord(s, &os->cy, delta);          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
651            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
652            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
653            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
654            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
655            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
656    };
657    
658          if (present & 0x10)  /* Output unknown capability sets */
659                  prs_io_uint8(s, &os->opcode);  static void
660    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
661    {
662            out_uint16_le(s, id);
663            out_uint16_le(s, length);
664    
665          return PRS_ERROR(s);          out_uint8p(s, caps, length - 4);
666  }  }
667    
668  /* Parse an pattern blt order */  #define RDP5_FLAG 0x0030
669  BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  /* Send a confirm active PDU */
670    static void
671    rdp_send_confirm_active(void)
672  {  {
673          if (present & 0x0001)          STREAM s;
674                  rdp_io_coord(s, &os->x, delta);          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
675            uint16 caplen =
676          if (present & 0x0002)                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
677                  rdp_io_coord(s, &os->y, delta);                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
678                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
679                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
680                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
681                    4 /* w2k fix, why? */ ;
682    
683          if (present & 0x0004)          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
                 rdp_io_coord(s, &os->cx, delta);  
684    
685          if (present & 0x0008)          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
686                  rdp_io_coord(s, &os->cy, delta);          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
687            out_uint16_le(s, (g_mcs_userid + 1001));
688    
689          if (present & 0x0010)          out_uint32_le(s, g_rdp_shareid);
690                  prs_io_uint8(s, &os->opcode);          out_uint16_le(s, 0x3ea);        /* userid */
691            out_uint16_le(s, sizeof(RDP_SOURCE));
692            out_uint16_le(s, caplen);
693    
694          if (present & 0x0020)          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
695                  rdp_io_colour(s, &os->bgcolour);          out_uint16_le(s, 0xd);  /* num_caps */
696            out_uint8s(s, 2);       /* pad */
697    
698          if (present & 0x0040)          rdp_out_general_caps(s);
699                  rdp_io_colour(s, &os->fgcolour);          rdp_out_bitmap_caps(s);
700            rdp_out_order_caps(s);
701            g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
702            rdp_out_colcache_caps(s);
703            rdp_out_activate_caps(s);
704            rdp_out_control_caps(s);
705            rdp_out_pointer_caps(s);
706            rdp_out_share_caps(s);
707    
708          rdp_io_brush(s, &os->brush, present >> 7);          rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
709            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
710            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
711            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
712    
713          return PRS_ERROR(s);          s_mark_end(s);
714            sec_send(s, sec_flags);
715  }  }
716    
717  /* Parse an screen blt order */  /* Process a general capability set */
718  BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  static void
719    rdp_process_general_caps(STREAM s)
720  {  {
721          if (present & 0x0001)          uint16 pad2octetsB;     /* rdp5 flags? */
                 rdp_io_coord(s, &os->x, delta);  
722    
723          if (present & 0x0002)          in_uint8s(s, 10);
724                  rdp_io_coord(s, &os->y, delta);          in_uint16_le(s, pad2octetsB);
725    
726          if (present & 0x0004)          if (!pad2octetsB)
727                  rdp_io_coord(s, &os->cx, delta);                  g_use_rdp5 = False;
728    }
729    
730          if (present & 0x0008)  /* Process a bitmap capability set */
731                  rdp_io_coord(s, &os->cy, delta);  static void
732    rdp_process_bitmap_caps(STREAM s)
733    {
734            uint16 width, height, bpp;
735    
736          if (present & 0x0010)          in_uint16_le(s, bpp);
737                  prs_io_uint8(s, &os->opcode);          in_uint8s(s, 6);
738    
739          if (present & 0x0020)          in_uint16_le(s, width);
740                  rdp_io_coord(s, &os->srcx, delta);          in_uint16_le(s, height);
741    
742          if (present & 0x0040)          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
                 rdp_io_coord(s, &os->srcy, delta);  
743    
744          return PRS_ERROR(s);          /*
745             * The server may limit bpp and change the size of the desktop (for
746             * example when shadowing another session).
747             */
748            if (g_server_bpp != bpp)
749            {
750                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
751                    g_server_bpp = bpp;
752            }
753            if (g_width != width || g_height != height)
754            {
755                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
756                            width, height);
757                    g_width = width;
758                    g_height = height;
759                    ui_resize_window();
760            }
761  }  }
762    
763  /* Parse a line order */  /* Process server capabilities */
764  BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  void
765    rdp_process_server_caps(STREAM s, uint16 length)
766  {  {
767          if (present & 0x0001)          int n;
768                  lsb_io_uint16(s, &os->mixmode);          uint8 *next, *start;
769            uint16 ncapsets, capset_type, capset_length;
770    
771          if (present & 0x0002)          start = s->p;
                 rdp_io_coord(s, &os->startx, delta);  
772    
773          if (present & 0x0004)          in_uint16_le(s, ncapsets);
774                  rdp_io_coord(s, &os->starty, delta);          in_uint8s(s, 2);        /* pad */
775    
776          if (present & 0x0008)          for (n = 0; n < ncapsets; n++)
777                  rdp_io_coord(s, &os->endx, delta);          {
778                    if (s->p > start + length)
779                            return;
780    
781          if (present & 0x0010)                  in_uint16_le(s, capset_type);
782                  rdp_io_coord(s, &os->endy, delta);                  in_uint16_le(s, capset_length);
783    
784          if (present & 0x0020)                  next = s->p + capset_length - 4;
                 rdp_io_colour(s, &os->bgcolour);  
785    
786          if (present & 0x0040)                  switch (capset_type)
787                  prs_io_uint8(s, &os->opcode);                  {
788                            case RDP_CAPSET_GENERAL:
789                                    rdp_process_general_caps(s);
790                                    break;
791    
792          rdp_io_pen(s, &os->pen, present >> 7);                          case RDP_CAPSET_BITMAP:
793                                    rdp_process_bitmap_caps(s);
794                                    break;
795                    }
796    
797          return PRS_ERROR(s);                  s->p = next;
798            }
799  }  }
800    
801  /* Parse an opaque rectangle order */  /* Respond to a demand active PDU */
802  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  static void
803    process_demand_active(STREAM s)
804  {  {
805          if (present & 0x01)          uint8 type;
806                  rdp_io_coord(s, &os->x, delta);          uint16 len_src_descriptor, len_combined_caps;
807    
808          if (present & 0x02)          in_uint32_le(s, g_rdp_shareid);
809                  rdp_io_coord(s, &os->y, delta);          in_uint16_le(s, len_src_descriptor);
810            in_uint16_le(s, len_combined_caps);
811            in_uint8s(s, len_src_descriptor);
812    
813          if (present & 0x04)          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
814                  rdp_io_coord(s, &os->cx, delta);          rdp_process_server_caps(s, len_combined_caps);
815    
816          if (present & 0x08)          rdp_send_confirm_active();
817                  rdp_io_coord(s, &os->cy, delta);          rdp_send_synchronise();
818            rdp_send_control(RDP_CTL_COOPERATE);
819            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
820            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
821            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
822            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
823            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
824    
825          if (present & 0x10)          if (g_use_rdp5)
826                  prs_io_uint8(s, &os->colour);          {
827                    rdp_enum_bmpcache2();
828                    rdp_send_fonts(3);
829            }
830            else
831            {
832                    rdp_send_fonts(1);
833                    rdp_send_fonts(2);
834            }
835    
836          return PRS_ERROR(s);          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
837            reset_order_state();
838  }  }
839    
840  /* Parse a desktop save order */  /* Process a colour pointer PDU */
841  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  void
842    process_colour_pointer_pdu(STREAM s)
843  {  {
844          if (present & 0x01)          uint16 x, y, width, height, cache_idx, masklen, datalen;
845                  lsb_io_uint32(s, &os->offset);          uint8 *mask, *data;
846            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);  
   
         if (present & 0x20)  
                 prs_io_uint8(s, &os->action);  
847    
848          return PRS_ERROR(s);          in_uint16_le(s, cache_idx);
849            in_uint16_le(s, x);
850            in_uint16_le(s, y);
851            in_uint16_le(s, width);
852            in_uint16_le(s, height);
853            in_uint16_le(s, masklen);
854            in_uint16_le(s, datalen);
855            in_uint8p(s, data, datalen);
856            in_uint8p(s, mask, masklen);
857            cursor = ui_create_cursor(x, y, width, height, mask, data);
858            ui_set_cursor(cursor);
859            cache_put_cursor(cache_idx, cursor);
860  }  }
861    
862  /* Parse a memory blt order */  /* Process a cached pointer PDU */
863  BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  void
864    process_cached_pointer_pdu(STREAM s)
865  {  {
866          if (present & 0x0001)          uint16 cache_idx;
         {  
                 prs_io_uint8(s, &os->cache_id);  
                 prs_io_uint8(s, &os->colour_table);  
         }  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x0010)  
                 rdp_io_coord(s, &os->cy, delta);  
867    
868          if (present & 0x0020)          in_uint16_le(s, cache_idx);
869                  prs_io_uint8(s, &os->opcode);          ui_set_cursor(cache_get_cursor(cache_idx));
   
         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);  
870  }  }
871    
872  /* Parse a 3-way blt order */  /* Process a system pointer PDU */
873  BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta)  void
874    process_system_pointer_pdu(STREAM s)
875  {  {
876          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);  
   
         if (present & 0x008000)  
                 lsb_io_uint16(s, &os->cache_idx);  
877    
878          if (present & 0x010000)          in_uint16(s, system_pointer_type);
879                  lsb_io_uint16(s, &os->unknown);          switch (system_pointer_type)
880            {
881                    case RDP_NULL_POINTER:
882                            ui_set_null_cursor();
883                            break;
884    
885          return PRS_ERROR(s);                  default:
886                            unimpl("System pointer message 0x%x\n", system_pointer_type);
887            }
888  }  }
889    
890  /* Parse a text order */  /* Process a pointer PDU */
891  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  static void
892    process_pointer_pdu(STREAM s)
893  {  {
894          if (present & 0x000001)          uint16 message_type;
895                  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);  
   
         if (present & 0x000200)  
                 lsb_io_uint16(s, &os->clipbottom);  
896    
897          if (present & 0x000400)          in_uint16_le(s, message_type);
898                  lsb_io_uint16(s, &os->boxleft);          in_uint8s(s, 2);        /* pad */
899    
900          if (present & 0x000800)          switch (message_type)
901                  lsb_io_uint16(s, &os->boxtop);          {
902                    case RDP_POINTER_MOVE:
903          if (present & 0x001000)                          in_uint16_le(s, x);
904                  lsb_io_uint16(s, &os->boxright);                          in_uint16_le(s, y);
905                            if (s_check(s))
906                                    ui_move_pointer(x, y);
907                            break;
908    
909          if (present & 0x002000)                  case RDP_POINTER_COLOR:
910                  lsb_io_uint16(s, &os->boxbottom);                          process_colour_pointer_pdu(s);
911                            break;
912    
913          if (present & 0x080000)                  case RDP_POINTER_CACHED:
914                  lsb_io_uint16(s, &os->x);                          process_cached_pointer_pdu(s);
915                            break;
916    
917          if (present & 0x100000)                  case RDP_POINTER_SYSTEM:
918                  lsb_io_uint16(s, &os->y);                          process_system_pointer_pdu(s);
919                            break;
920    
921          if (present & 0x200000)                  default:
922          {                          unimpl("Pointer message 0x%x\n", message_type);
                 prs_io_uint8(s, &os->length);  
                 prs_io_uint8s(s, os->text, os->length);  
923          }          }
   
         return PRS_ERROR(s);  
924  }  }
925    
926    /* Process bitmap updates */
927  /* SECONDARY ORDERS */  void
928    process_bitmap_updates(STREAM s)
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
929  {  {
930          BOOL res = True;          uint16 num_updates;
931            uint16 left, top, right, bottom, width, height;
932          res = res ? lsb_io_uint16(s, &rso->length) : False;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
933          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          uint8 *data, *bmpdata;
934          res = res ? prs_io_uint8 (s, &rso->type  ) : False;          int i;
   
         return res;  
 }  
935    
936  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)          in_uint16_le(s, num_updates);
 {  
         BOOL res = True;  
937    
938          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          for (i = 0; i < num_updates; i++)
939          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;          {
940          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;                  in_uint16_le(s, left);
941          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;                  in_uint16_le(s, top);
942          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;                  in_uint16_le(s, right);
943          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;                  in_uint16_le(s, bottom);
944          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;                  in_uint16_le(s, width);
945                    in_uint16_le(s, height);
946                    in_uint16_le(s, bpp);
947                    Bpp = (bpp + 7) / 8;
948                    in_uint16_le(s, compress);
949                    in_uint16_le(s, bufsize);
950    
951          rbo->data = s->data + s->offset;                  cx = right - left + 1;
952          s->offset += rbo->bufsize;                  cy = bottom - top + 1;
953    
954          return res;                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
955  }                         left, top, right, bottom, width, height, Bpp, compress));
956    
957  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)                  if (!compress)
958  {                  {
959          BOOL res = True;                          int y;
960                            bmpdata = (uint8 *) xmalloc(width * height * Bpp);
961                            for (y = 0; y < height; y++)
962                            {
963                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
964                                              width * Bpp);
965                            }
966                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
967                            xfree(bmpdata);
968                            continue;
969                    }
970    
         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;  
971    
972          rbo->data = s->data + s->offset;                  if (compress & 0x400)
973          s->offset += rbo->size;                  {
974                            size = bufsize;
975                    }
976                    else
977                    {
978                            in_uint8s(s, 2);        /* pad */
979                            in_uint16_le(s, size);
980                            in_uint8s(s, 4);        /* line_size, final_size */
981                    }
982                    in_uint8p(s, data, size);
983                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
984                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
985                    {
986                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
987                    }
988                    else
989                    {
990                            DEBUG_RDP5(("Failed to decompress data\n"));
991                    }
992    
993          return res;                  xfree(bmpdata);
994            }
995  }  }
996    
997  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process a palette update */
998    void
999    process_palette(STREAM s)
1000  {  {
1001          COLOURENTRY *entry;          COLOURENTRY *entry;
1002            COLOURMAP map;
1003            HCOLOURMAP hmap;
1004          int i;          int i;
1005    
1006          prs_io_uint8(s, &colours->cache_id);          in_uint8s(s, 2);        /* pad */
1007          lsb_io_uint16(s, &colours->map.ncolours);          in_uint16_le(s, map.ncolours);
1008            in_uint8s(s, 2);        /* pad */
1009    
1010            map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1011    
1012            DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1013    
1014          for (i = 0; i < colours->map.ncolours; i++)          for (i = 0; i < map.ncolours; i++)
1015          {          {
1016                  entry = &colours->map.colours[i];                  entry = &map.colours[i];
1017                  prs_io_uint8(s, &entry->blue);                  in_uint8(s, entry->red);
1018                  prs_io_uint8(s, &entry->green);                  in_uint8(s, entry->green);
1019                  prs_io_uint8(s, &entry->red);                  in_uint8(s, entry->blue);
                 s->offset++;  
1020          }          }
1021    
1022          return True;          hmap = ui_create_colourmap(&map);
1023  }          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;  
                 }  
         }  
1024    
1025          return res;          xfree(map.colours);
1026  }  }
1027    
1028    /* Process an update PDU */
1029  /* CAPABILITIES */  static void
1030    process_update_pdu(STREAM s)
 /* Construct a general capability set */  
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
1031  {  {
1032          caps->os_major_type = 1;          uint16 update_type, count;
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
1033    
1034  /* 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;  
1035    
1036          res = lsb_io_uint16(s, &pkt_length);          ui_begin_update();
1037          if (pkt_length != length)          switch (update_type)
1038          {          {
1039                  ERROR("Unrecognised capabilities size\n");                  case RDP_UPDATE_ORDERS:
1040                  return False;                          in_uint8s(s, 2);        /* pad */
1041          }                          in_uint16_le(s, count);
1042                            in_uint8s(s, 2);        /* pad */
1043                            process_orders(s, count);
1044                            break;
1045    
1046          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;                  case RDP_UPDATE_BITMAP:
1047          res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;                          process_bitmap_updates(s);
1048          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;  
1049    
1050          res = lsb_io_uint16(s, &pkt_length);                  case RDP_UPDATE_PALETTE:
1051          if (pkt_length != length)                          process_palette(s);
1052          {                          break;
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
1053    
1054          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  case RDP_UPDATE_SYNCHRONIZE:
1055          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;  
1056    
1057          res = lsb_io_uint16(s, &pkt_length);                  default:
1058          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
1059          }          }
1060            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;  
1061  }  }
1062    
1063  /* Parse single bitmap cache information structure */  /* Process a disconnect PDU */
1064  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  void
1065    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1066  {  {
1067          if (!lsb_io_uint16(s, &info->entries      ))          in_uint32_le(s, *ext_disc_reason);
                 return False;  
1068    
1069          if (!lsb_io_uint16(s, &info->max_cell_size))          DEBUG(("Received disconnect PDU\n"));
                 return False;  
   
         return True;  
1070  }  }
1071    
1072  /* Parse bitmap cache capability set */  /* Process data PDU */
1073  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  static BOOL
1074    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1075  {  {
1076          uint16 length = RDP_CAPLEN_BMPCACHE;          uint8 data_pdu_type;
1077          uint16 pkt_length = length;          uint8 ctype;
1078          BOOL res;          uint16 clen;
1079          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;  
1080    
1081          for (i = 0; i < 3; i++)          uint32 roff, rlen;
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
1082    
1083          return res;          struct stream *ns = &(g_mppc_dict.ns);
 }  
1084    
1085  /* Construct a control capability set */          in_uint8s(s, 6);        /* shareid, pad, streamid */
1086  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)          in_uint16(s, len);
1087  {          in_uint8(s, data_pdu_type);
1088          caps->control_interest = 2;          in_uint8(s, ctype);
1089          caps->detach_interest = 2;          in_uint16(s, clen);
1090  }          clen -= 18;
1091    
1092  /* 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)  
1093          {          {
1094                  ERROR("Unrecognised capabilities size\n");                  if (len > RDP_MPPC_DICT_SIZE)
1095                  return False;                          error("error decompressed packet size exceeds max\n");
1096          }                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1097                            error("error while decompressing packet\n");
1098    
1099          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;  
1100    
1101          return res;                  /* allocate memory and copy the uncompressed data into the temporary stream */
1102  }                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
1103    
1104  /* 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)  
 {  
 }  
1105    
1106  /* Parse activation capability set */                  ns->size = rlen;
1107  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)                  ns->end = (ns->data + ns->size);
1108  {                  ns->p = ns->data;
1109          uint16 length = RDP_CAPLEN_ACTIVATE;                  ns->rdp_hdr = ns->p;
         uint16 pkt_length = length;  
         BOOL res;  
1110    
1111          res = lsb_io_uint16(s, &pkt_length);                  s = ns;
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
1112          }          }
1113    
1114          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)  
1115          {          {
1116                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
1117                  return False;                          process_update_pdu(s);
1118          }                          break;
1119    
1120          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_DATA_PDU_CONTROL:
1121          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          DEBUG(("Received Control PDU\n"));
1122                            break;
1123    
1124          return res;                  case RDP_DATA_PDU_SYNCHRONISE:
1125  }                          DEBUG(("Received Sync PDU\n"));
1126                            break;
1127    
1128  /* Construct a share capability set */                  case RDP_DATA_PDU_POINTER:
1129  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)                          process_pointer_pdu(s);
1130  {                          break;
 }  
1131    
1132  /* Parse share capability set */                  case RDP_DATA_PDU_BELL:
1133  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                          ui_bell();
1134  {                          break;
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
1135    
1136          res = lsb_io_uint16(s, &pkt_length);                  case RDP_DATA_PDU_LOGON:
1137          if (pkt_length != length)                          DEBUG(("Received Logon PDU\n"));
1138          {                          /* User logged on */
1139                  ERROR("Unrecognised capabilities size\n");                          break;
                 return False;  
         }  
1140    
1141          res = res ? lsb_io_uint16(s, &caps->userid) : False;                  case RDP_DATA_PDU_DISCONNECT:
1142          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                          process_disconnect_pdu(s, ext_disc_reason);
1143                            return True;
1144    
1145          return res;                  default:
1146                            unimpl("data PDU %d\n", data_pdu_type);
1147            }
1148            return False;
1149  }  }
1150    
1151  /* Construct a colour cache capability set */  /* Process incoming packets */
1152  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  /* nevers gets out of here till app is done */
1153    void
1154    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1155  {  {
1156          caps->cache_size = 6;          while (rdp_loop(deactivated, ext_disc_reason))
1157                    ;
1158  }  }
1159    
1160  /* Parse colour cache capability set */  /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1161  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
1162    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1163  {  {
1164          uint16 length = RDP_CAPLEN_COLCACHE;          uint8 type;
1165          uint16 pkt_length = length;          BOOL disc = False;      /* True when a disconnect PDU was received */
1166          BOOL res;          BOOL cont = True;
1167            STREAM s;
1168    
1169          res = lsb_io_uint16(s, &pkt_length);          while (cont)
         if (pkt_length != length)  
1170          {          {
1171                  ERROR("Unrecognised capabilities size\n");                  s = rdp_recv(&type);
1172                  return False;                  if (s == NULL)
1173                            return False;
1174                    switch (type)
1175                    {
1176                            case RDP_PDU_DEMAND_ACTIVE:
1177                                    process_demand_active(s);
1178                                    *deactivated = False;
1179                                    break;
1180                            case RDP_PDU_DEACTIVATE:
1181                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1182                                    *deactivated = True;
1183                                    break;
1184                            case RDP_PDU_DATA:
1185                                    disc = process_data_pdu(s, ext_disc_reason);
1186                                    break;
1187                            case 0:
1188                                    break;
1189                            default:
1190                                    unimpl("PDU %d\n", type);
1191                    }
1192                    if (disc)
1193                            return False;
1194                    cont = g_next_packet < s->end;
1195          }          }
1196            return True;
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
   
         return res;  
1197  }  }
1198    
1199  uint8 canned_caps[] = {  /* Establish a connection up to the RDP layer */
1200  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  BOOL
1201  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,
1202  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)  
1203  {  {
1204          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");  
1205                  return False;                  return False;
         }  
1206    
1207          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1208            return True;
1209    }
1210    
1211          return res;  /* Disconnect from the RDP layer */
1212    void
1213    rdp_disconnect(void)
1214    {
1215            sec_disconnect();
1216  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26