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

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

  ViewVC Help
Powered by ViewVC 1.1.26