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

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

  ViewVC Help
Powered by ViewVC 1.1.26