/[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 637 by stargo, Mon Mar 15 14:49:12 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    
35  /* Create an RC4 key and transfer it to the server */  uint8 *g_next_packet;
36  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  
 };  
37    
38  /* Send license certificate and related data to the server */  #if WITH_DEBUG
39  void rdp_send_cert(HCONN conn)  static uint32 g_packetno;
40  {  #endif
         mcs_init_data(conn);  
         prs_io_uint8s(&conn->out, precanned_cert_packet, sizeof(precanned_cert_packet));  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
41    
42  /* Initialise RDP transport packet */  /* Receive an RDP packet */
43  void rdp_init(HCONN conn)  static STREAM
44    rdp_recv(uint8 * type)
45  {  {
46          mcs_init_data(conn);          static STREAM rdp_s;
47          PUSH_LAYER(conn->out, rdp_offset, 6);          uint16 length, pdu_type;
 }  
48    
49  /* Transmit RDP transport packet */          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
50  void rdp_send(HCONN conn, uint16 pdu_type)          {
51  {                  rdp_s = sec_recv();
52          RDP_HEADER hdr;                  if (rdp_s == NULL)
53          int length;                          return NULL;
54    
55          POP_LAYER(conn->out, rdp_offset);                  g_next_packet = rdp_s->p;
56          length = conn->out.end - conn->out.offset;          }
57          rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);          else
58          rdp_io_header(&conn->out, &hdr);          {
59          mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);                  rdp_s->p = g_next_packet;
60  }          }
61    
62  /* Initialise RDP transport data packet */          in_uint16_le(rdp_s, length);
63  void rdp_init_data(HCONN conn)          /* 32k packets are really 8, keepalive fix */
64  {          if (length == 0x8000)
65          mcs_init_data(conn);          {
66          PUSH_LAYER(conn->out, rdp_offset, 18);                  g_next_packet += 8;
67  }                  *type = 0;
68                    return rdp_s;
69            }
70            in_uint16_le(rdp_s, pdu_type);
71            in_uint8s(rdp_s, 2);    /* userid */
72            *type = pdu_type & 0xf;
73    
74  /* Transmit RDP transport data packet */  #if WITH_DEBUG
75  void rdp_send_data(HCONN conn, uint16 data_pdu_type)          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
76  {          hexdump(g_next_packet, length);
77          RDP_HEADER hdr;  #endif /*  */
         RDP_DATA_HEADER datahdr;  
         int length = conn->out.end - conn->out.offset;  
78    
79          POP_LAYER(conn->out, rdp_offset);          g_next_packet += length;
80          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);  
81  }  }
82    
83  void rdp_send_confirm_active(HCONN conn, uint32 shareid, int width, int height)  /* Initialise an RDP data packet */
84    static STREAM
85    rdp_init_data(int maxlen)
86  {  {
87          RDP_ACTIVE_PDU active;          STREAM s;
   
         rdp_init(conn);  
         rdp_make_active_pdu(&active, shareid, conn->mcs_userid, width, height);  
         rdp_io_active_pdu(&conn->out, &active, RDP_PDU_CONFIRM_ACTIVE);  
         MARK_END(conn->out);  
         rdp_send(conn, RDP_PDU_CONFIRM_ACTIVE);  
 }  
88    
89  void rdp_send_synchronize(HCONN conn)          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
90  {          s_push_layer(s, rdp_hdr, 18);
         RDP_SYNCHRONISE_PDU sync;  
91    
92          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);  
93  }  }
94    
95  void rdp_send_control(HCONN conn, uint16 action)  /* Send an RDP data packet */
96    static void
97    rdp_send_data(STREAM s, uint8 data_pdu_type)
98  {  {
99          RDP_CONTROL_PDU control;          uint16 length;
   
         rdp_init_data(conn);  
         rdp_make_control_pdu(&control, action);  
         rdp_io_control_pdu(&conn->out, &control);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_CONTROL);  
 }  
100    
101  void rdp_send_fonts(HCONN conn, uint16 seqno)          s_pop_layer(s, rdp_hdr);
102  {          length = s->end - s->p;
         RDP_FONT_PDU fonts;  
103    
104          rdp_init_data(conn);          out_uint16_le(s, length);
105          rdp_make_font_pdu(&fonts, seqno);          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
106          rdp_io_font_pdu(&conn->out, &fonts);          out_uint16_le(s, (g_mcs_userid + 1001));
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_FONT2);  
 }  
107    
108  void rdp_send_input(HCONN conn, uint16 message_type, uint16 device_flags,          out_uint32_le(s, g_rdp_shareid);
109                                  uint16 param1, uint16 param2)          out_uint8(s, 0);        /* pad */
110  {          out_uint8(s, 1);        /* streamid */
111          RDP_INPUT_PDU input;          out_uint16_le(s, (length - 14));
112            out_uint8(s, data_pdu_type);
113            out_uint8(s, 0);        /* compress_type */
114            out_uint16(s, 0);       /* compress_len */
115    
116          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);  
117  }  }
118    
119  BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  /* Output a string in Unicode */
120    void
121    rdp_out_unistr(STREAM s, char *string, int len)
122  {  {
123          RDP_HEADER hdr;          int i = 0, j = 0;
124    
125          conn->in.offset = conn->in.rdp_offset;          len += 2;
126    
127          if (conn->in.offset >= conn->in.end)          while (i < len)
128          {          {
129                  if (!mcs_recv(conn, False))                  s->p[i++] = string[j++];
130                          return False;                  s->p[i++] = 0;
131          }          }
132    
133          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);  
134  }  }
135    
136  /* Construct an RDP header */  /* Input a string in Unicode
137  void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,   *
138                       uint16 userid)   * Returns str_len of string
139     */
140    int
141    rdp_in_unistr(STREAM s, char *string, int uni_len)
142  {  {
143          hdr->length = length;          int i = 0;
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
 }  
144    
145  /* Parse an RDP header */          while (i < uni_len / 2)
146  BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)          {
147  {                  in_uint8a(s, &string[i++], 1);
148          BOOL res = True;                  in_uint8s(s, 1);
149            }
         res = res ? lsb_io_uint16(s, &hdr->length  ) : False;  
         res = res ? lsb_io_uint16(s, &hdr->pdu_type) : False;  
         if ((hdr->pdu_type & 0xf) != RDP_PDU_DEACTIVATE)  
                 res = res ? lsb_io_uint16(s, &hdr->userid  ) : False;  
150    
151          return res;          return i - 1;
152  }  }
153    
 /* 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;  
 }  
154    
155  /* Parse a data header */  /* Parse a logon info packet */
156  BOOL rdp_io_data_header(STREAM s, RDP_DATA_HEADER *hdr)  static void
157    rdp_send_logon_info(uint32 flags, char *domain, char *user,
158                        char *password, char *program, char *directory)
159  {  {
160          BOOL res = True;          char *ipaddr = tcp_get_address();
161            int len_domain = 2 * strlen(domain);
162            int len_user = 2 * strlen(user);
163            int len_password = 2 * strlen(password);
164            int len_program = 2 * strlen(program);
165            int len_directory = 2 * strlen(directory);
166            int len_ip = 2 * strlen(ipaddr);
167            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
168            int packetlen = 0;
169            uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
170            STREAM s;
171            time_t t = time(NULL);
172            time_t tzone;
173    
174          res = res ? lsb_io_uint32(s, &hdr->shareid      ) : False;  #if 0
175          res = res ? prs_io_uint8 (s, &hdr->pad          ) : False;          // enable rdp compression
176          res = res ? prs_io_uint8 (s, &hdr->streamid     ) : False;          flags |= RDP_COMPRESSION;
177          res = res ? lsb_io_uint16(s, &hdr->length       ) : False;  #endif
         res = res ? prs_io_uint8 (s, &hdr->data_pdu_type) : False;  
         res = res ? prs_io_uint8 (s, &hdr->compress_type) : False;  
         res = res ? lsb_io_uint16(s, &hdr->compress_len ) : False;  
178    
179          return res;          if (!g_use_rdp5 || 1 == g_server_rdp_version)
180  }          {
181                    DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
182    
183  BOOL rdp_io_present(STREAM s, uint32 *present, uint8 flags, int size)                  s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
184  {                               + len_program + len_directory + 10);
         uint8 bits;  
         int i;  
185    
186          if (flags & RDP_ORDER_SMALL)                  out_uint32(s, 0);
187          {                  out_uint32_le(s, flags);
188                  size--;                  out_uint16_le(s, len_domain);
189                    out_uint16_le(s, len_user);
190                    out_uint16_le(s, len_password);
191                    out_uint16_le(s, len_program);
192                    out_uint16_le(s, len_directory);
193                    rdp_out_unistr(s, domain, len_domain);
194                    rdp_out_unistr(s, user, len_user);
195                    rdp_out_unistr(s, password, len_password);
196                    rdp_out_unistr(s, program, len_program);
197                    rdp_out_unistr(s, directory, len_directory);
198          }          }
199            else
         if (flags & RDP_ORDER_TINY)  
200          {          {
201                  if (size < 2)                  flags |= RDP_LOGON_BLOB;
202                          return False;                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
203                    packetlen = 4 + /* Unknown uint32 */
204                            4 +     /* flags */
205                            2 +     /* len_domain */
206                            2 +     /* len_user */
207                            (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
208                            (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
209                            2 +     /* len_program */
210                            2 +     /* len_directory */
211                            (0 < len_domain ? len_domain : 2) +     /* domain */
212                            len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
213                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
214                            (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
215                            2 +     /* Client ip length */
216                            len_ip +        /* Client ip */
217                            2 +     /* DLL string length */
218                            len_dll +       /* DLL string */
219                            2 +     /* Unknown */
220                            2 +     /* Unknown */
221                            64 +    /* Time zone #0 */
222                            2 +     /* Unknown */
223                            64 +    /* Time zone #1 */
224                            32;     /* Unknown */
225    
226                    s = sec_init(sec_flags, packetlen);
227                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
228    
229                    out_uint32(s, 0);       /* Unknown */
230                    out_uint32_le(s, flags);
231                    out_uint16_le(s, len_domain);
232                    out_uint16_le(s, len_user);
233                    if (flags & RDP_LOGON_AUTO)
234                    {
235                            out_uint16_le(s, len_password);
236    
237                  size -= 2;                  }
238          }                  if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
239                    {
240                            out_uint16_le(s, 0);
241                    }
242                    out_uint16_le(s, len_program);
243                    out_uint16_le(s, len_directory);
244                    if (0 < len_domain)
245                            rdp_out_unistr(s, domain, len_domain);
246                    else
247                            out_uint16_le(s, 0);
248                    rdp_out_unistr(s, user, len_user);
249                    if (flags & RDP_LOGON_AUTO)
250                    {
251                            rdp_out_unistr(s, password, len_password);
252                    }
253                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
254                    {
255                            out_uint16_le(s, 0);
256                    }
257                    if (0 < len_program)
258                    {
259                            rdp_out_unistr(s, program, len_program);
260    
261          *present = 0;                  }
262          for (i = 0; i < size; i++)                  else
263          {                  {
264                  prs_io_uint8(s, &bits);                          out_uint16_le(s, 0);
265                  *present |= bits << (i * 8);                  }
266          }                  if (0 < len_directory)
267                    {
268                            rdp_out_unistr(s, directory, len_directory);
269                    }
270                    else
271                    {
272                            out_uint16_le(s, 0);
273                    }
274                    out_uint16_le(s, 2);
275                    out_uint16_le(s, len_ip + 2);   /* Length of client ip */
276                    rdp_out_unistr(s, ipaddr, len_ip);
277                    out_uint16_le(s, len_dll + 2);
278                    rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
279    
280          return True;                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
281  }                  out_uint32_le(s, tzone);
282    
283  BOOL rdp_io_coord(STREAM s, uint16 *coord, BOOL delta)                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
284  {                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
         uint8 change;  
         BOOL res;  
285    
286          if (delta)                  out_uint32_le(s, 0x0a0000);
287          {                  out_uint32_le(s, 0x050000);
288                  res = prs_io_uint8(s, &change);                  out_uint32_le(s, 3);
289                  *coord += (char)change;                  out_uint32_le(s, 0);
290          }                  out_uint32_le(s, 0);
         else  
         {  
                 res = lsb_io_uint16(s, coord);  
         }  
291    
292          return res;                  rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
293  }                  out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
294    
295  BOOL rdp_io_colour(STREAM s, uint8 *colour)                  out_uint32_le(s, 0x30000);
296  {                  out_uint32_le(s, 0x050000);
297          BOOL res;                  out_uint32_le(s, 2);
298                    out_uint32(s, 0);
299                    out_uint32_le(s, 0xffffffc4);
300                    out_uint32_le(s, 0xfffffffe);
301                    out_uint32_le(s, g_rdp5_performanceflags);
302                    out_uint32(s, 0);
303    
         res = prs_io_uint8(s, colour);  
         s->offset += 2;  
304    
305          return res;          }
306            s_mark_end(s);
307            sec_send(s, sec_flags);
308  }  }
309    
310  BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours)  /* Send a control PDU */
311    static void
312    rdp_send_control(uint16 action)
313  {  {
314          int datasize;          STREAM s;
315    
316          lsb_io_uint16(s, &colours->ncolours);          s = rdp_init_data(8);
         datasize = colours->ncolours * 3;  
317    
318          if (datasize > sizeof(colours->colours))          out_uint16_le(s, action);
319                  return False;          out_uint16(s, 0);       /* userid */
320            out_uint32(s, 0);       /* control id */
321    
322          memcpy(colours->colours, s->data + s->offset, datasize);          s_mark_end(s);
323          s->offset += datasize;          rdp_send_data(s, RDP_DATA_PDU_CONTROL);
         return True;  
324  }  }
325    
326  BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds)  /* Send a synchronisation PDU */
327    static void
328    rdp_send_synchronise(void)
329  {  {
330          uint8 present;          STREAM s;
331    
332          prs_io_uint8(s, &present);          s = rdp_init_data(4);
333    
334          if (present & 1)          out_uint16_le(s, 1);    /* type */
335                  rdp_io_coord(s, &bounds->left, False);          out_uint16_le(s, 1002);
         else if (present & 16)  
                 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);  
336    
337          return True;          s_mark_end(s);
338            rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
339  }  }
340    
341  BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present)  /* Send a single input event */
342    void
343    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
344  {  {
345          BOOL res = True;          STREAM s;
346    
347          if (present & 1)          s = rdp_init_data(16);
                 res = res ? prs_io_uint8(s, &pen->style) : False;  
348    
349          if (present & 2)          out_uint16_le(s, 1);    /* number of events */
350                  res = res ? prs_io_uint8(s, &pen->width) : False;          out_uint16(s, 0);       /* pad */
351    
352          if (present & 4)          out_uint32_le(s, time);
353                  res = res ? rdp_io_colour(s, &pen->colour) : False;          out_uint16_le(s, message_type);
354            out_uint16_le(s, device_flags);
355            out_uint16_le(s, param1);
356            out_uint16_le(s, param2);
357    
358          return res;          s_mark_end(s);
359            rdp_send_data(s, RDP_DATA_PDU_INPUT);
360  }  }
361    
362  BOOL rdp_io_brush(STREAM s, BRUSH *brush, uint32 present)  /* Send an (empty) font information PDU */
363    static void
364    rdp_send_fonts(uint16 seq)
365  {  {
366          BOOL res = True;          STREAM s;
   
         if (present & 1)  
                 res = res ? prs_io_uint8(s, &brush->xorigin) : False;  
367    
368          if (present & 2)          s = rdp_init_data(8);
                 res = res ? prs_io_uint8(s, &brush->yorigin) : False;  
369    
370          if (present & 4)          out_uint16(s, 0);       /* number of fonts */
371                  res = res ? prs_io_uint8(s, &brush->style) : False;          out_uint16_le(s, 0x3e); /* unknown */
372            out_uint16_le(s, seq);  /* unknown */
373            out_uint16_le(s, 0x32); /* entry size */
374    
375          if (present & 8)          s_mark_end(s);
376                  res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;          rdp_send_data(s, RDP_DATA_PDU_FONT2);
   
         if (present & 16)  
                 res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;  
   
         return res;  
377  }  }
378    
379  /* Construct a confirm/demand active PDU */  /* Output general capability set */
380  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid,  static void
381                                  int width, int height)  rdp_out_general_caps(STREAM s)
382  {  {
383          memset(pdu, 0, sizeof(*pdu));          out_uint16_le(s, RDP_CAPSET_GENERAL);
384          pdu->shareid = shareid;          out_uint16_le(s, RDP_CAPLEN_GENERAL);
         pdu->userid  = 1002;  
         pdu->source_len = sizeof(RDP_SOURCE);  
         memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));  
385    
386          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          out_uint16_le(s, 1);    /* OS major type */
387                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          out_uint16_le(s, 3);    /* OS minor type */
388                  + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE          out_uint16_le(s, 0x200);        /* Protocol version */
389                  + RDP_CAPLEN_UNKNOWN;          out_uint16(s, 0);       /* Pad */
390          pdu->num_caps = 0xD;          out_uint16(s, 0);       /* Compression types */
391            out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
392          rdp_make_general_caps (&pdu->general_caps );          /* Pad, according to T.128. 0x40d seems to
393          rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);             trigger
394          rdp_make_order_caps   (&pdu->order_caps   );             the server to start sending RDP5 packets.
395          rdp_make_bmpcache_caps(&pdu->bmpcache_caps);             However, the value is 0x1d04 with W2KTSK and
396          rdp_make_control_caps (&pdu->control_caps );             NT4MS. Hmm.. Anyway, thankyou, Microsoft,
397          rdp_make_activate_caps(&pdu->activate_caps);             for sending such information in a padding
398          rdp_make_pointer_caps (&pdu->pointer_caps );             field.. */
399          rdp_make_share_caps   (&pdu->share_caps, userid);          out_uint16(s, 0);       /* Update capability */
400          rdp_make_colcache_caps(&pdu->colcache_caps);          out_uint16(s, 0);       /* Remote unshare capability */
401            out_uint16(s, 0);       /* Compression level */
402            out_uint16(s, 0);       /* Pad */
403  }  }
404    
405  /* Parse a confirm/demand active PDU */  /* Output bitmap capability set */
406  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  static void
407    rdp_out_bitmap_caps(STREAM s)
408  {  {
409          uint16 capset;          out_uint16_le(s, RDP_CAPSET_BITMAP);
410          uint16 length;          out_uint16_le(s, RDP_CAPLEN_BITMAP);
         BOOL res;  
         int i;  
   
         res = lsb_io_uint32(s, &pdu->shareid);  
   
         if (pdutype == RDP_PDU_CONFIRM_ACTIVE)  
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
   
         res = res ? lsb_io_uint16(s, &pdu->source_len) : False;  
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
   
         if (pdu->source_len > 48)  
         {  
                 ERROR("RDP source descriptor too long\n");  
                 return False;  
         }  
   
         res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;  
         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;  
411    
412                          if (!lsb_io_uint16(s, &capset))          out_uint16_le(s, 8);    /* Preferred BPP */
413                                  return False;          out_uint16_le(s, 1);    /* Receive 1 BPP */
414            out_uint16_le(s, 1);    /* Receive 4 BPP */
415                          switch (capset)          out_uint16_le(s, 1);    /* Receive 8 BPP */
416                          {          out_uint16_le(s, 800);  /* Desktop width */
417                          case RDP_CAPSET_GENERAL:          out_uint16_le(s, 600);  /* Desktop height */
418                                  res = rdp_io_general_caps (s, &pdu->general_caps );          out_uint16(s, 0);       /* Pad */
419                                  break;          out_uint16(s, 0);       /* Allow resize */
420                          case RDP_CAPSET_BITMAP:          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
421                                  res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );          out_uint16(s, 0);       /* Unknown */
422                                  break;          out_uint16_le(s, 1);    /* Unknown */
423                          case RDP_CAPSET_ORDER:          out_uint16(s, 0);       /* Pad */
                                 res = rdp_io_order_caps   (s, &pdu->order_caps   );  
                                 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);  
   
                                 if (!lsb_io_uint16(s, &length))  
                                         return False;  
   
                                 s->offset += (length - 4);  
                         }  
                 }  
         }  
   
         return res;  
424  }  }
425    
426  /* Construct a control PDU */  /* Output order capability set */
427  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  static void
428    rdp_out_order_caps(STREAM s)
429  {  {
430          pdu->action = action;          uint8 order_caps[32];
         pdu->userid = 0;  
         pdu->controlid = 0;  
 }  
431    
 /* Parse a control PDU */  
 BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  
 {  
         BOOL res = True;  
432    
433          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;          memset(order_caps, 0, 32);
434          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;          order_caps[0] = 1;      /* dest blt */
435          res = res ? lsb_io_uint32(s, &pdu->controlid) : False;          order_caps[1] = 1;      /* pat blt */
436            order_caps[2] = 1;      /* screen blt */
437            order_caps[3] = 1;      /* required for memblt? */
438            order_caps[8] = 1;      /* line */
439            order_caps[9] = 1;      /* line */
440            order_caps[10] = 1;     /* rect */
441            order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */
442            order_caps[13] = 1;     /* memblt */
443            order_caps[14] = 1;     /* triblt */
444            order_caps[22] = 1;     /* polyline */
445            order_caps[27] = 1;     /* text2 */
446            out_uint16_le(s, RDP_CAPSET_ORDER);
447            out_uint16_le(s, RDP_CAPLEN_ORDER);
448    
449          return res;          out_uint8s(s, 20);      /* Terminal desc, pad */
450            out_uint16_le(s, 1);    /* Cache X granularity */
451            out_uint16_le(s, 20);   /* Cache Y granularity */
452            out_uint16(s, 0);       /* Pad */
453            out_uint16_le(s, 1);    /* Max order level */
454            out_uint16_le(s, 0x147);        /* Number of fonts */
455            out_uint16_le(s, 0x2a); /* Capability flags */
456            out_uint8p(s, order_caps, 32);  /* Orders supported */
457            out_uint16_le(s, 0x6a1);        /* Text capability flags */
458            out_uint8s(s, 6);       /* Pad */
459            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
460            out_uint32(s, 0);       /* Unknown */
461            out_uint32_le(s, 0x4e4);        /* Unknown */
462  }  }
463    
464  /* Construct a synchronisation PDU */  /* Output bitmap cache capability set */
465  void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  static void
466    rdp_out_bmpcache_caps(STREAM s)
467  {  {
468          pdu->type = 1;          int Bpp;
469          pdu->userid = userid;          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
470  }          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
471    
472  /* Parse a synchronisation PDU */          Bpp = (g_server_bpp + 7) / 8;
473  BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)          out_uint8s(s, 24);      /* unused */
474  {          out_uint16_le(s, 0x258);        /* entries */
475          BOOL res = True;          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
476            out_uint16_le(s, 0x12c);        /* entries */
477          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
478          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          out_uint16_le(s, 0x106);        /* entries */
479            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
         return res;  
480  }  }
481    
482  /* Parse a single input event */  /* Output control capability set */
483  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  static void
484    rdp_out_control_caps(STREAM s)
485  {  {
486          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_CONTROL);
487            out_uint16_le(s, RDP_CAPLEN_CONTROL);
         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;  
   
         if (!res)  
                 return False;  
   
         switch (evt->message_type)  
         {  
         case RDP_INPUT_CODEPOINT:  
         case RDP_INPUT_VIRTKEY:  
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 break;  
         case RDP_INPUT_SYNCHRONIZE:  
         case RDP_INPUT_SCANCODE:  
         case RDP_INPUT_MOUSE:  
                 res = res ? lsb_io_uint16(s, &evt->param1) : False;  
                 res = res ? lsb_io_uint16(s, &evt->param2) : False;  
                 break;  
         default:  
                 NOTIMP("input type %d\n", evt->message_type);  
                 return False;  
         }  
488    
489          return res;          out_uint16(s, 0);       /* Control capabilities */
490            out_uint16(s, 0);       /* Remote detach */
491            out_uint16_le(s, 2);    /* Control interest */
492            out_uint16_le(s, 2);    /* Detach interest */
493  }  }
494    
495  /* Construct an input PDU */  /* Output activation capability set */
496  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  static void
497                          uint16 device_flags, uint16 param1, uint16 param2)  rdp_out_activate_caps(STREAM s)
498  {  {
499          uint32 now = time(NULL);          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
500            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
501    
502          pdu->num_events = 1;          out_uint16(s, 0);       /* Help key */
503          pdu->pad = 0;          out_uint16(s, 0);       /* Help index key */
504            out_uint16(s, 0);       /* Extended help key */
505          pdu->event[0].event_time = now;          out_uint16(s, 0);       /* Window activate */
         pdu->event[0].message_type = message_type;  
         pdu->event[0].device_flags = device_flags;  
         pdu->event[0].param1 = param1;  
         pdu->event[0].param2 = param2;  
506  }  }
507    
508  /* Parse an input PDU */  /* Output pointer capability set */
509  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
510    rdp_out_pointer_caps(STREAM s)
511  {  {
512          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_POINTER);
513          int i;          out_uint16_le(s, RDP_CAPLEN_POINTER);
   
         res = res ? lsb_io_uint16(s, &pdu->num_events) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  
514    
515          if (pdu->num_events > RDP_MAX_EVENTS)          out_uint16(s, 0);       /* Colour pointer */
516          {          out_uint16_le(s, 20);   /* Cache size */
                 ERROR("Too many events in one PDU\n");  
                 return False;  
         }  
   
         for (i = 0; i < pdu->num_events; i++)  
         {  
                 res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;  
         }  
   
         return res;  
517  }  }
518    
519  /* Construct a font information PDU */  /* Output share capability set */
520  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)  static void
521    rdp_out_share_caps(STREAM s)
522  {  {
523          pdu->num_fonts = 0;          out_uint16_le(s, RDP_CAPSET_SHARE);
524          pdu->unknown1 = 0x3e;          out_uint16_le(s, RDP_CAPLEN_SHARE);
525          pdu->unknown2 = seqno;  
526          pdu->entry_size = RDP_FONT_INFO_SIZE;          out_uint16(s, 0);       /* userid */
527            out_uint16(s, 0);       /* pad */
528  }  }
529    
530  /* Parse a font information structure */  /* Output colour cache capability set */
531  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  static void
532    rdp_out_colcache_caps(STREAM s)
533  {  {
534          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
535            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
         res = res ? prs_io_uint8s(s,  font->name, 32 ) : False;  
         res = res ? lsb_io_uint16(s, &font->flags    ) : False;  
         res = res ? lsb_io_uint16(s, &font->width    ) : False;  
         res = res ? lsb_io_uint16(s, &font->height   ) : False;  
         res = res ? lsb_io_uint16(s, &font->xaspect  ) : False;  
         res = res ? lsb_io_uint16(s, &font->yaspect  ) : False;  
         res = res ? lsb_io_uint32(s, &font->signature) : False;  
         res = res ? lsb_io_uint16(s, &font->codepage ) : False;  
         res = res ? lsb_io_uint16(s, &font->ascent   ) : False;  
536    
537          return res;          out_uint16_le(s, 6);    /* cache size */
538            out_uint16(s, 0);       /* pad */
539  }  }
540    
541  /* Parse a font information PDU */  static uint8 canned_caps[] = {
542  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,
543  {          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
544          BOOL res = True;          0x00, 0x00, 0x00, 0x00, 0x00,
545          int i;          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546            0x00, 0x00, 0x00, 0x00, 0x00,
547            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
548            0x00, 0x00, 0x00, 0x00, 0x00,
549            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
550            0x00, 0x00, 0x00, 0x00, 0x00,
551            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
552            0x0C, 0x00, 0x08, 0x00, 0x01,
553            0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,
554            0x10, 0x00, 0x34, 0x00, 0xFE,
555            0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,
556            0xFE, 0x00, 0x08, 0x00, 0xFE,
557            0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,
558            0xFE, 0x00, 0x80, 0x00, 0xFE,
559            0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,
560            0x02, 0x00, 0x00, 0x00
561    };
562    
563          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;  /* Output unknown capability sets (number 13, 12, 14 and 16) */
564          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;  static void
565          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;  rdp_out_unknown_caps(STREAM s)
566          res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  {
567            out_uint16_le(s, RDP_CAPSET_UNKNOWN);
568            out_uint16_le(s, 0x58);
569    
570            out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);
571    }
572    
573    #define RDP5_FLAG 0x0030
574    /* Send a confirm active PDU */
575    static void
576    rdp_send_confirm_active(void)
577    {
578            STREAM s;
579            uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
580            uint16 caplen =
581                    RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
582                    RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
583                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
584                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;
585    
586            s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
587    
588            out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
589            out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
590            out_uint16_le(s, (g_mcs_userid + 1001));
591    
592            out_uint32_le(s, g_rdp_shareid);
593            out_uint16_le(s, 0x3ea);        /* userid */
594            out_uint16_le(s, sizeof(RDP_SOURCE));
595            out_uint16_le(s, caplen);
596    
597            out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
598            out_uint16_le(s, 0xd);  /* num_caps */
599            out_uint8s(s, 2);       /* pad */
600    
601            rdp_out_general_caps(s);
602            rdp_out_bitmap_caps(s);
603            rdp_out_order_caps(s);
604            rdp_out_bmpcache_caps(s);
605            rdp_out_colcache_caps(s);
606            rdp_out_activate_caps(s);
607            rdp_out_control_caps(s);
608            rdp_out_pointer_caps(s);
609            rdp_out_share_caps(s);
610            rdp_out_unknown_caps(s);
611    
612            s_mark_end(s);
613            sec_send(s, sec_flags);
614    }
615    
616    /* Respond to a demand active PDU */
617    static void
618    process_demand_active(STREAM s)
619    {
620            uint8 type;
621    
622            in_uint32_le(s, g_rdp_shareid);
623    
624            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
625    
626            rdp_send_confirm_active();
627            rdp_send_synchronise();
628            rdp_send_control(RDP_CTL_COOPERATE);
629            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
630            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
631            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
632            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
633            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
634            rdp_send_fonts(1);
635            rdp_send_fonts(2);
636            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
637            reset_order_state();
638    }
639    
640    /* Process a colour pointer PDU */
641    void
642    process_colour_pointer_pdu(STREAM s)
643    {
644            uint16 x, y, width, height, cache_idx, masklen, datalen;
645            uint8 *mask, *data;
646            HCURSOR cursor;
647    
648            in_uint16_le(s, cache_idx);
649            in_uint16_le(s, x);
650            in_uint16_le(s, y);
651            in_uint16_le(s, width);
652            in_uint16_le(s, height);
653            in_uint16_le(s, masklen);
654            in_uint16_le(s, datalen);
655            in_uint8p(s, data, datalen);
656            in_uint8p(s, mask, masklen);
657            cursor = ui_create_cursor(x, y, width, height, mask, data);
658            ui_set_cursor(cursor);
659            cache_put_cursor(cache_idx, cursor);
660    }
661    
662    /* Process a cached pointer PDU */
663    void
664    process_cached_pointer_pdu(STREAM s)
665    {
666            uint16 cache_idx;
667    
668            in_uint16_le(s, cache_idx);
669            ui_set_cursor(cache_get_cursor(cache_idx));
670    }
671    
672    /* Process a system pointer PDU */
673    void
674    process_system_pointer_pdu(STREAM s)
675    {
676            uint16 system_pointer_type;
677    
678          if (pdu->num_fonts > RDP_MAX_FONTS)          in_uint16(s, system_pointer_type);
679            switch (system_pointer_type)
680          {          {
681                  ERROR("Too many fonts in one PDU\n");                  case RDP_NULL_POINTER:
682                  return False;                          ui_set_null_cursor();
683          }                          break;
684    
685          for (i = 0; i < pdu->num_fonts; i++)                  default:
686          {                          unimpl("System pointer message 0x%x\n", system_pointer_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
687          }          }
   
         return res;  
688  }  }
689    
690  /* Parse a pointer PDU */  /* Process a pointer PDU */
691  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  static void
692    process_pointer_pdu(STREAM s)
693  {  {
694          BOOL res = True;          uint16 message_type;
695            uint16 x, y;
696    
697          res = res ? lsb_io_uint16(s, &ptr->message) : False;          in_uint16_le(s, message_type);
698          res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;          in_uint8s(s, 2);        /* pad */
699    
700          switch (ptr->message)          switch (message_type)
701          {          {
702                  case RDP_POINTER_MOVE:                  case RDP_POINTER_MOVE:
703                          res = res ? lsb_io_uint16(s, &ptr->x      ) : False;                          in_uint16_le(s, x);
704                          res = res ? lsb_io_uint16(s, &ptr->y      ) : False;                          in_uint16_le(s, y);
705                            if (s_check(s))
706                                    ui_move_pointer(x, y);
707                          break;                          break;
         }  
   
         return res;  
 }  
   
 /* Parse an update PDU */  
 BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint16(s, &pdu->update_type) : False;  
         res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;  
   
         return res;  
 }  
   
   
 /* PRIMARY ORDERS */  
   
 /* 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);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x08)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x10)  
                 prs_io_uint8(s, &os->opcode);  
   
         return PRS_ERROR(s);  
 }  
   
 /* Parse an pattern blt order */  
 BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x0010)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x0040)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         rdp_io_brush(s, &os->brush, present >> 7);  
   
         return PRS_ERROR(s);  
 }  
   
 /* Parse an screen blt order */  
 BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->y, delta);  
708    
709          if (present & 0x0004)                  case RDP_POINTER_COLOR:
710                  rdp_io_coord(s, &os->cx, delta);                          process_colour_pointer_pdu(s);
711                            break;
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x0010)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x0020)  
                 rdp_io_coord(s, &os->srcx, delta);  
   
         if (present & 0x0040)  
                 rdp_io_coord(s, &os->srcy, delta);  
   
         return PRS_ERROR(s);  
 }  
   
 /* Parse a line order */  
 BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
                 lsb_io_uint16(s, &os->mixmode);  
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->startx, delta);  
   
         if (present & 0x0004)  
                 rdp_io_coord(s, &os->starty, delta);  
   
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->endx, delta);  
   
         if (present & 0x0010)  
                 rdp_io_coord(s, &os->endy, delta);  
   
         if (present & 0x0020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x0040)  
                 prs_io_uint8(s, &os->opcode);  
   
         rdp_io_pen(s, &os->pen, present >> 7);  
   
         return PRS_ERROR(s);  
 }  
   
 /* Parse an opaque rectangle order */  
 BOOL rdp_io_rect_order(STREAM s, RECT_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);  
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->cx, delta);  
712    
713          if (present & 0x08)                  case RDP_POINTER_CACHED:
714                  rdp_io_coord(s, &os->cy, delta);                          process_cached_pointer_pdu(s);
715                            break;
716    
717          if (present & 0x10)                  case RDP_POINTER_SYSTEM:
718                  prs_io_uint8(s, &os->colour);                          process_system_pointer_pdu(s);
719                            break;
720    
721          return PRS_ERROR(s);                  default:
722                            unimpl("Pointer message 0x%x\n", message_type);
723            }
724  }  }
725    
726  /* Parse a desktop save order */  /* Process bitmap updates */
727  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  void
728    process_bitmap_updates(STREAM s)
729  {  {
730          if (present & 0x01)          uint16 num_updates;
731                  lsb_io_uint32(s, &os->offset);          uint16 left, top, right, bottom, width, height;
732            uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
733          if (present & 0x02)          uint8 *data, *bmpdata;
734                  rdp_io_coord(s, &os->left, delta);          int i;
   
         if (present & 0x04)  
                 rdp_io_coord(s, &os->top, delta);  
   
         if (present & 0x08)  
                 rdp_io_coord(s, &os->right, delta);  
   
         if (present & 0x10)  
                 rdp_io_coord(s, &os->bottom, delta);  
   
         if (present & 0x20)  
                 prs_io_uint8(s, &os->action);  
735    
736          return PRS_ERROR(s);          in_uint16_le(s, num_updates);
 }  
737    
738  /* Parse a memory blt order */          for (i = 0; i < num_updates; i++)
 BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
739          {          {
740                  prs_io_uint8(s, &os->cache_id);                  in_uint16_le(s, left);
741                  prs_io_uint8(s, &os->colour_table);                  in_uint16_le(s, top);
742          }                  in_uint16_le(s, right);
743                    in_uint16_le(s, bottom);
744          if (present & 0x0002)                  in_uint16_le(s, width);
745                  rdp_io_coord(s, &os->x, delta);                  in_uint16_le(s, height);
746                    in_uint16_le(s, bpp);
747          if (present & 0x0004)                  Bpp = (bpp + 7) / 8;
748                  rdp_io_coord(s, &os->y, delta);                  in_uint16_le(s, compress);
749                    in_uint16_le(s, bufsize);
750    
751          if (present & 0x0008)                  cx = right - left + 1;
752                  rdp_io_coord(s, &os->cx, delta);                  cy = bottom - top + 1;
753    
754          if (present & 0x0010)                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
755                  rdp_io_coord(s, &os->cy, delta);                         left, top, right, bottom, width, height, Bpp, compress));
756    
757          if (present & 0x0020)                  /* Server may limit bpp - this is how we find out */
758                  prs_io_uint8(s, &os->opcode);                  if (g_server_bpp != bpp)
759                    {
760          if (present & 0x0040)                          warning("Server limited colour depth to %d bits\n", bpp);
761                  rdp_io_coord(s, &os->srcx, delta);                          g_server_bpp = bpp;
762                    }
763    
764          if (present & 0x0080)                  if (!compress)
765                  rdp_io_coord(s, &os->srcy, delta);                  {
766                            int y;
767                            bmpdata = (uint8 *) xmalloc(width * height * Bpp);
768                            for (y = 0; y < height; y++)
769                            {
770                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
771                                              width * Bpp);
772                            }
773                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
774                            xfree(bmpdata);
775                            continue;
776                    }
777    
         if (present & 0x0100)  
                 lsb_io_uint16(s, &os->cache_idx);  
778    
779          return PRS_ERROR(s);                  if (compress & 0x400)
780  }                  {
781                            size = bufsize;
782                    }
783                    else
784                    {
785                            in_uint8s(s, 2);        /* pad */
786                            in_uint16_le(s, size);
787                            in_uint8s(s, 4);        /* line_size, final_size */
788                    }
789                    in_uint8p(s, data, size);
790                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
791                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
792                    {
793                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
794                    }
795                    else
796                    {
797                            DEBUG_RDP5(("Failed to decompress data\n"));
798                    }
799    
800  /* Parse a 3-way blt order */                  xfree(bmpdata);
 BOOL rdp_io_triblt_order(STREAM s, TRIBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x000001)  
         {  
                 prs_io_uint8(s, &os->cache_id);  
                 prs_io_uint8(s, &os->colour_table);  
801          }          }
   
         if (present & 0x000002)  
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x000004)  
                 rdp_io_coord(s, &os->y, delta);  
   
         if (present & 0x000008)  
                 rdp_io_coord(s, &os->cx, delta);  
   
         if (present & 0x000010)  
                 rdp_io_coord(s, &os->cy, delta);  
   
         if (present & 0x000020)  
                 prs_io_uint8(s, &os->opcode);  
   
         if (present & 0x000040)  
                 rdp_io_coord(s, &os->srcx, delta);  
   
         if (present & 0x000080)  
                 rdp_io_coord(s, &os->srcy, delta);  
   
         if (present & 0x000100)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x000200)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         rdp_io_brush(s, &os->brush, present >> 10);  
   
         if (present & 0x008000)  
                 lsb_io_uint16(s, &os->cache_idx);  
   
         if (present & 0x010000)  
                 lsb_io_uint16(s, &os->unknown);  
   
         return PRS_ERROR(s);  
802  }  }
803    
804  /* Parse a text order */  /* Process a palette update */
805  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  void
806    process_palette(STREAM s)
807  {  {
808          if (present & 0x000001)          COLOURENTRY *entry;
809                  prs_io_uint8(s, &os->font);          COLOURMAP map;
810            HCOLOURMAP hmap;
811          if (present & 0x000002)          int i;
                 prs_io_uint8(s, &os->flags);  
   
         if (present & 0x000004)  
                 prs_io_uint8(s, &os->unknown);  
   
         if (present & 0x000008)  
                 prs_io_uint8(s, &os->mixmode);  
   
         if (present & 0x000010)  
                 rdp_io_colour(s, &os->fgcolour);  
   
         if (present & 0x000020)  
                 rdp_io_colour(s, &os->bgcolour);  
   
         if (present & 0x000040)  
                 lsb_io_uint16(s, &os->clipleft);  
   
         if (present & 0x000080)  
                 lsb_io_uint16(s, &os->cliptop);  
   
         if (present & 0x000100)  
                 lsb_io_uint16(s, &os->clipright);  
   
         if (present & 0x000200)  
                 lsb_io_uint16(s, &os->clipbottom);  
   
         if (present & 0x000400)  
                 lsb_io_uint16(s, &os->boxleft);  
   
         if (present & 0x000800)  
                 lsb_io_uint16(s, &os->boxtop);  
   
         if (present & 0x001000)  
                 lsb_io_uint16(s, &os->boxright);  
812    
813          if (present & 0x002000)          in_uint8s(s, 2);        /* pad */
814                  lsb_io_uint16(s, &os->boxbottom);          in_uint16_le(s, map.ncolours);
815            in_uint8s(s, 2);        /* pad */
816    
817          if (present & 0x080000)          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
                 lsb_io_uint16(s, &os->x);  
818    
819          if (present & 0x100000)          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
                 lsb_io_uint16(s, &os->y);  
820    
821          if (present & 0x200000)          for (i = 0; i < map.ncolours; i++)
822          {          {
823                  prs_io_uint8(s, &os->length);                  entry = &map.colours[i];
824                  prs_io_uint8s(s, os->text, os->length);                  in_uint8(s, entry->red);
825                    in_uint8(s, entry->green);
826                    in_uint8(s, entry->blue);
827          }          }
828    
829          return PRS_ERROR(s);          hmap = ui_create_colourmap(&map);
830  }          ui_set_colourmap(hmap);
   
831    
832  /* SECONDARY ORDERS */          xfree(map.colours);
   
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
 {  
         BOOL res = True;  
   
         res = res ? lsb_io_uint16(s, &rso->length) : False;  
         res = res ? lsb_io_uint16(s, &rso->flags ) : False;  
         res = res ? prs_io_uint8 (s, &rso->type  ) : False;  
   
         return res;  
833  }  }
834    
835  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  /* Process an update PDU */
836    static void
837    process_update_pdu(STREAM s)
838  {  {
839          BOOL res = True;          uint16 update_type, count;
   
         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;  
840    
841          rbo->data = s->data + s->offset;          in_uint16_le(s, update_type);
         s->offset += rbo->bufsize;  
842    
843          return res;          switch (update_type)
844  }          {
845                    case RDP_UPDATE_ORDERS:
846  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)                          in_uint8s(s, 2);        /* pad */
847  {                          in_uint16_le(s, count);
848          BOOL res = True;                          in_uint8s(s, 2);        /* pad */
849                            process_orders(s, count);
850          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                          break;
         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;  
   
         rbo->data = s->data + s->offset;  
         s->offset += rbo->size;  
851    
852          return res;                  case RDP_UPDATE_BITMAP:
853  }                          process_bitmap_updates(s);
854                            break;
855    
856  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)                  case RDP_UPDATE_PALETTE:
857  {                          process_palette(s);
858          COLOURENTRY *entry;                          break;
         int i;  
859    
860          prs_io_uint8(s, &colours->cache_id);                  case RDP_UPDATE_SYNCHRONIZE:
861          lsb_io_uint16(s, &colours->map.ncolours);                          break;
862    
863          for (i = 0; i < colours->map.ncolours; i++)                  default:
864          {                          unimpl("update %d\n", update_type);
                 entry = &colours->map.colours[i];  
                 prs_io_uint8(s, &entry->blue);  
                 prs_io_uint8(s, &entry->green);  
                 prs_io_uint8(s, &entry->red);  
                 s->offset++;  
865          }          }
866    
         return True;  
867  }  }
868    
869  BOOL rdp_io_fontcache_order(STREAM s, RDP_FONTCACHE_ORDER *font)  /* Process data PDU */
870    static void
871    process_data_pdu(STREAM s)
872  {  {
873          RDP_FONT_GLYPH *glyph;          uint8 data_pdu_type;
874          BOOL res = True;          uint8 ctype;
875          int i, j, datasize;          uint16 clen;
876          uint8 in, out;          int roff, rlen, len, ret;
877            static struct stream ns;
878            static signed char *dict = 0;
879    
880          res = res ? prs_io_uint8(s, &font->font   ) : False;          in_uint8s(s, 6);        /* shareid, pad, streamid */
881          res = res ? prs_io_uint8(s, &font->nglyphs) : False;          in_uint16(s, len);
882            in_uint8(s, data_pdu_type);
883            in_uint8(s, ctype);
884            in_uint16(s, clen);
885            clen -= 18;
886    
887          for (i = 0; i < font->nglyphs; i++)  #if 0
888            if (ctype & 0x20)
889          {          {
890                  glyph = &font->glyphs[i];                  if (!dict)
                 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++)  
891                  {                  {
892                          in = glyph->data[j];                          dict = (signed char *) malloc(8200 * sizeof(signed char));
893                          out = 0;                          dict = (signed char *) memset(dict, 0, 8200 * sizeof(signed char));
                         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;  
894                  }                  }
         }  
895    
896          return res;                  ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen);
 }  
897    
898                    len -= 18;
899    
900  /* CAPABILITIES */                  ns.data = xrealloc(ns.data, len);
   
 /* Construct a general capability set */  
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
   
 /* Parse general capability set */  
 BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_GENERAL;  
         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 ? lsb_io_uint16(s, &caps->os_major_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;  
         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;  
901    
902          res = lsb_io_uint16(s, &pkt_length);                  ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len);
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
903    
904          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  ns.size = len;
905          res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;                  ns.end = ns.data + ns.size;
906          res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;                  ns.p = ns.data;
907          res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;                  ns.rdp_hdr = ns.p;
         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;  
908    
909          res = lsb_io_uint16(s, &pkt_length);                  s = &ns;
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
910          }          }
911    #endif
912    
913          res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;          switch (data_pdu_type)
         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;  
 }  
   
 /* Parse single bitmap cache information structure */  
 BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  
 {  
         if (!lsb_io_uint16(s, &info->entries      ))  
                 return False;  
   
         if (!lsb_io_uint16(s, &info->max_cell_size))  
                 return False;  
   
         return True;  
 }  
   
 /* Parse bitmap cache capability set */  
 BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BMPCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         for (i = 0; i < 6; i++)  
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
   
         for (i = 0; i < 3; i++)  
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
   
         return res;  
 }  
   
 /* Construct a control capability set */  
 void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)  
 {  
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
   
 /* Parse control capability set */  
 BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
914          {          {
915                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
916                  return False;                          process_update_pdu(s);
917          }                          break;
918    
919          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;                  case RDP_DATA_PDU_POINTER:
920          res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;                          process_pointer_pdu(s);
921          res = res ? lsb_io_uint16(s, &caps->control_interest) : False;                          break;
         res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  
922    
923          return res;                  case RDP_DATA_PDU_BELL:
924  }                          ui_bell();
925                            break;
926    
927  /* Construct an activation capability set */                  case RDP_DATA_PDU_LOGON:
928  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)                          DEBUG(("Received Logon PDU\n"));
929  {                          /* User logged on */
930  }                          break;
931    
932  /* Parse activation capability set */                  case RDP_DATA_PDU_DISCONNECT:
933  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)                          /* Normally received when user logs out or disconnects from a
934  {                             console session on Windows XP and 2003 Server */
935          uint16 length = RDP_CAPLEN_ACTIVATE;                          DEBUG(("Received disconnect PDU\n"));
936          uint16 pkt_length = length;                          break;
         BOOL res;  
937    
938          res = lsb_io_uint16(s, &pkt_length);                  default:
939          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
940          }          }
   
         res = res ? lsb_io_uint16(s, &caps->help_key         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_index_key   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->help_extended_key) : False;  
         res = res ? lsb_io_uint16(s, &caps->window_activate  ) : False;  
   
         return res;  
 }  
   
 /* Construct a pointer capability set */  
 void rdp_make_pointer_caps(RDP_POINTER_CAPS *caps)  
 {  
         caps->colour_pointer = 0;  
         caps->cache_size = 20;  
941  }  }
942    
943  /* Parse pointer capability set */  /* Process incoming packets */
944  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  BOOL
945    rdp_main_loop(void)
946  {  {
947          uint16 length = RDP_CAPLEN_POINTER;          uint8 type;
948          uint16 pkt_length = length;          STREAM s;
         BOOL res;  
949    
950          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
951          {          {
952                  ERROR("Unrecognised capabilities size\n");                  switch (type)
953                  return False;                  {
954          }                          case RDP_PDU_DEMAND_ACTIVE:
955                                    process_demand_active(s);
956          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                                  break;
         res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;  
957    
958          return res;                          case RDP_PDU_DEACTIVATE:
959  }                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
960                                    /* We thought we could detect a clean
961                                       shutdown of the session by this
962                                       packet, but it seems Windows 2003
963                                       is sending us one of these when we
964                                       reconnect to a disconnected session
965                                       return True; */
966                                    break;
967    
968  /* Construct a share capability set */                          case RDP_PDU_DATA:
969  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)                                  process_data_pdu(s);
970  {                                  break;
 }  
971    
972  /* Parse share capability set */                          case 0:
973  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                                  break;
 {  
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
974    
975          res = lsb_io_uint16(s, &pkt_length);                          default:
976          if (pkt_length != length)                                  unimpl("PDU %d\n", type);
977          {                  }
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
978          }          }
979            return True;
980          res = res ? lsb_io_uint16(s, &caps->userid) : False;          /* We want to detect if we got a clean shutdown, but we
981          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;             can't. Se above.  
982               return False;  */
         return res;  
 }  
   
 /* Construct a colour cache capability set */  
 void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  
 {  
         caps->cache_size = 6;  
983  }  }
984    
985  /* Parse colour cache capability set */  /* Establish a connection up to the RDP layer */
986  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
987    rdp_connect(char *server, uint32 flags, char *domain, char *password,
988                char *command, char *directory)
989  {  {
990          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");  
991                  return False;                  return False;
         }  
   
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
992    
993          return res;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
994            return True;
995  }  }
996    
997  uint8 canned_caps[] = {  /* Disconnect from the RDP layer */
998  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  void
999  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)  
1000  {  {
1001          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;  
1002  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26