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

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

  ViewVC Help
Powered by ViewVC 1.1.26