/[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 676 by astrand, Tue Apr 20 07:01:21 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;  
134  }  }
135    
136  /* Disconnect from the RDP layer */  /* Input a string in Unicode
137  void rdp_disconnect(HCONN conn)   *
138     * Returns str_len of string
139     */
140    int
141    rdp_in_unistr(STREAM s, char *string, int uni_len)
142  {  {
143          mcs_disconnect(conn);          int i = 0;
 }  
144    
145  /* Construct an RDP header */          while (i < uni_len / 2)
146  void rdp_make_header(RDP_HEADER *hdr, uint16 length, uint16 pdu_type,          {
147                       uint16 userid)                  in_uint8a(s, &string[i++], 1);
148  {                  in_uint8s(s, 1);
149          hdr->length = length;          }
         hdr->pdu_type = pdu_type | 0x10; /* Version 1 */  
         hdr->userid = userid + 1001;  
 }  
   
 /* Parse an RDP header */  
 BOOL rdp_io_header(STREAM s, RDP_HEADER *hdr)  
 {  
         BOOL res = True;  
   
         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;
367    
368          if (present & 1)          s = rdp_init_data(8);
                 res = res ? prs_io_uint8(s, &brush->xorigin) : False;  
369    
370          if (present & 2)          out_uint16(s, 0);       /* number of fonts */
371                  res = res ? prs_io_uint8(s, &brush->yorigin) : 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 & 4)          s_mark_end(s);
376                  res = res ? prs_io_uint8(s, &brush->style) : False;          rdp_send_data(s, RDP_DATA_PDU_FONT2);
   
         if (present & 8)  
                 res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;  
   
         if (present & 16)  
                 res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;  
   
         return res;  
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));  
   
         pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER  
                 + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE  
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
385    
386          rdp_make_general_caps (&pdu->general_caps );          out_uint16_le(s, 1);    /* OS major type */
387          rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);          out_uint16_le(s, 3);    /* OS minor type */
388          rdp_make_order_caps   (&pdu->order_caps   );          out_uint16_le(s, 0x200);        /* Protocol version */
389          rdp_make_bmpcache_caps(&pdu->bmpcache_caps);          out_uint16(s, 0);       /* Pad */
390          rdp_make_control_caps (&pdu->control_caps );          out_uint16(s, 0);       /* Compression types */
391          rdp_make_activate_caps(&pdu->activate_caps);          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
392          rdp_make_pointer_caps (&pdu->pointer_caps );          /* Pad, according to T.128. 0x40d seems to
393          rdp_make_share_caps   (&pdu->share_caps, userid);             trigger
394          rdp_make_colcache_caps(&pdu->colcache_caps);             the server to start sending RDP5 packets.
395               However, the value is 0x1d04 with W2KTSK and
396               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
397               for sending such information in a padding
398               field.. */
399            out_uint16(s, 0);       /* Update capability */
400            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;  
         }  
411    
412          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
413          res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;          out_uint16_le(s, 1);    /* Receive 1 BPP */
414          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;          out_uint16_le(s, 1);    /* Receive 4 BPP */
415            out_uint16_le(s, 1);    /* Receive 8 BPP */
416          if (s->marshall)          out_uint16_le(s, 800);  /* Desktop width */
417          {          out_uint16_le(s, 600);  /* Desktop height */
418                  capset = RDP_CAPSET_GENERAL;          out_uint16(s, 0);       /* Pad */
419                  res = res ? lsb_io_uint16(s, &capset) : False;          out_uint16(s, 0);       /* Allow resize */
420                  res = res ? rdp_io_general_caps(s, &pdu->general_caps) : False;          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
421            out_uint16(s, 0);       /* Unknown */
422                  capset = RDP_CAPSET_BITMAP;          out_uint16_le(s, 1);    /* Unknown */
423                  res = res ? lsb_io_uint16(s, &capset) : False;          out_uint16(s, 0);       /* Pad */
424                  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;  
   
                         if (!lsb_io_uint16(s, &capset))  
                                 return False;  
425    
426                          switch (capset)  /* Output order capability set */
427                          {  static void
428                          case RDP_CAPSET_GENERAL:  rdp_out_order_caps(STREAM s)
429                                  res = rdp_io_general_caps (s, &pdu->general_caps );  {
430                                  break;          uint8 order_caps[32];
                         case RDP_CAPSET_BITMAP:  
                                 res = rdp_io_bitmap_caps  (s, &pdu->bitmap_caps  );  
                                 break;  
                         case RDP_CAPSET_ORDER:  
                                 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);  
431    
                                 if (!lsb_io_uint16(s, &length))  
                                         return False;  
432    
433                                  s->offset += (length - 4);          memset(order_caps, 0, 32);
434                          }          order_caps[0] = 1;      /* dest blt */
435                  }          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 control PDU */  /* Output bitmap cache capability set */
465  void rdp_make_control_pdu(RDP_CONTROL_PDU *pdu, uint16 action)  static void
466    rdp_out_bmpcache_caps(STREAM s)
467  {  {
468          pdu->action = action;          int Bpp;
469          pdu->userid = 0;          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
470          pdu->controlid = 0;          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
471    
472            Bpp = (g_server_bpp + 7) / 8;
473            out_uint8s(s, 24);      /* unused */
474            out_uint16_le(s, 0x258);        /* entries */
475            out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
476            out_uint16_le(s, 0x12c);        /* entries */
477            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
478            out_uint16_le(s, 0x106);        /* entries */
479            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
480  }  }
481    
482  /* Parse a control PDU */  /* Output control capability set */
483  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  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_uint16(s, &pdu->action   ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;  
         res = res ? lsb_io_uint32(s, &pdu->controlid) : 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 a synchronisation PDU */  /* Output activation capability set */
496  void rdp_make_synchronise_pdu(RDP_SYNCHRONISE_PDU *pdu, uint16 userid)  static void
497    rdp_out_activate_caps(STREAM s)
498  {  {
499          pdu->type = 1;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
500          pdu->userid = userid;          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
501    
502            out_uint16(s, 0);       /* Help key */
503            out_uint16(s, 0);       /* Help index key */
504            out_uint16(s, 0);       /* Extended help key */
505            out_uint16(s, 0);       /* Window activate */
506  }  }
507    
508  /* Parse a synchronisation PDU */  /* Output pointer capability set */
509  BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)  static void
510    rdp_out_pointer_caps(STREAM s)
511  {  {
512          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_POINTER);
513            out_uint16_le(s, RDP_CAPLEN_POINTER);
         res = res ? lsb_io_uint16(s, &pdu->type  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->userid) : False;  
514    
515          return res;          out_uint16(s, 0);       /* Colour pointer */
516            out_uint16_le(s, 20);   /* Cache size */
517  }  }
518    
519  /* Parse a single input event */  /* Output share capability set */
520  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  static void
521    rdp_out_share_caps(STREAM s)
522  {  {
523          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_SHARE);
524            out_uint16_le(s, RDP_CAPLEN_SHARE);
         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;  
525    
526          if (!res)          out_uint16(s, 0);       /* userid */
527                  return False;          out_uint16(s, 0);       /* pad */
   
         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;  
         }  
   
         return res;  
528  }  }
529    
530  /* Construct an input PDU */  /* Output colour cache capability set */
531  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  static void
532                          uint16 device_flags, uint16 param1, uint16 param2)  rdp_out_colcache_caps(STREAM s)
533  {  {
534          uint32 now = time(NULL);          out_uint16_le(s, RDP_CAPSET_COLCACHE);
535            out_uint16_le(s, RDP_CAPLEN_COLCACHE);
536    
537          pdu->num_events = 1;          out_uint16_le(s, 6);    /* cache size */
538          pdu->pad = 0;          out_uint16(s, 0);       /* pad */
   
         pdu->event[0].event_time = now;  
         pdu->event[0].message_type = message_type;  
         pdu->event[0].device_flags = device_flags;  
         pdu->event[0].param1 = param1;  
         pdu->event[0].param2 = param2;  
539  }  }
540    
541  /* Parse an input PDU */  static uint8 canned_caps[] = {
542  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_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_events) : False;  /* Output unknown capability sets (number 13, 12, 14 and 16) */
564          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;  static void
565    rdp_out_unknown_caps(STREAM s)
566    {
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            uint16 i;
622            uint16 p_bpp;
623    
624          if (pdu->num_events > RDP_MAX_EVENTS)          in_uint32_le(s, g_rdp_shareid);
         {  
                 ERROR("Too many events in one PDU\n");  
                 return False;  
         }  
625    
626          for (i = 0; i < pdu->num_events; i++)          /* scan for prefered bpp */
627            while (s_check_rem(s, 6))
628          {          {
629                  res = res ? rdp_io_input_event(s, &pdu->event[i]) : False;                  in_uint16_le(s, i);
630                    if (i == RDP_CAPSET_BITMAP)
631                    {
632                            in_uint16_le(s, i);
633                            if (i == RDP_CAPLEN_BITMAP)
634                            {
635                                    in_uint16_le(s, p_bpp);
636                                    if (p_bpp == 8 || p_bpp == 15 || p_bpp == 16 || p_bpp == 24)
637                                    {
638                                            if (p_bpp < g_server_bpp)
639                                            {
640                                                    warning("Server limited colour depth to %d bits\n",
641                                                            p_bpp);
642                                                    g_server_bpp = p_bpp;
643                                            }
644                                            break;
645                                    }
646                            }
647                    }
648          }          }
649    
         return res;  
 }  
650    
651  /* Construct a font information PDU */          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
 void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)  
 {  
         pdu->num_fonts = 0;  
         pdu->unknown1 = 0x3e;  
         pdu->unknown2 = seqno;  
         pdu->entry_size = RDP_FONT_INFO_SIZE;  
 }  
652    
653  /* Parse a font information structure */          rdp_send_confirm_active();
654  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)          rdp_send_synchronise();
655            rdp_send_control(RDP_CTL_COOPERATE);
656            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
657            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
658            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
659            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
660            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
661            rdp_send_fonts(1);
662            rdp_send_fonts(2);
663            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */
664            reset_order_state();
665    }
666    
667    /* Process a colour pointer PDU */
668    void
669    process_colour_pointer_pdu(STREAM s)
670    {
671            uint16 x, y, width, height, cache_idx, masklen, datalen;
672            uint8 *mask, *data;
673            HCURSOR cursor;
674    
675            in_uint16_le(s, cache_idx);
676            in_uint16_le(s, x);
677            in_uint16_le(s, y);
678            in_uint16_le(s, width);
679            in_uint16_le(s, height);
680            in_uint16_le(s, masklen);
681            in_uint16_le(s, datalen);
682            in_uint8p(s, data, datalen);
683            in_uint8p(s, mask, masklen);
684            cursor = ui_create_cursor(x, y, width, height, mask, data);
685            ui_set_cursor(cursor);
686            cache_put_cursor(cache_idx, cursor);
687    }
688    
689    /* Process a cached pointer PDU */
690    void
691    process_cached_pointer_pdu(STREAM s)
692    {
693            uint16 cache_idx;
694    
695            in_uint16_le(s, cache_idx);
696            ui_set_cursor(cache_get_cursor(cache_idx));
697    }
698    
699    /* Process a system pointer PDU */
700    void
701    process_system_pointer_pdu(STREAM s)
702  {  {
703          BOOL res = True;          uint16 system_pointer_type;
   
         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;  
   
         return res;  
 }  
704    
705  /* Parse a font information PDU */          in_uint16(s, system_pointer_type);
706  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)          switch (system_pointer_type)
 {  
         BOOL res = True;  
         int i;  
   
         res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;  
         res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;  
   
         if (pdu->num_fonts > RDP_MAX_FONTS)  
707          {          {
708                  ERROR("Too many fonts in one PDU\n");                  case RDP_NULL_POINTER:
709                  return False;                          ui_set_null_cursor();
710          }                          break;
711    
712          for (i = 0; i < pdu->num_fonts; i++)                  default:
713          {                          unimpl("System pointer message 0x%x\n", system_pointer_type);
                 res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;  
714          }          }
   
         return res;  
715  }  }
716    
717  /* Parse a pointer PDU */  /* Process a pointer PDU */
718  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)  static void
719    process_pointer_pdu(STREAM s)
720  {  {
721          BOOL res = True;          uint16 message_type;
722            uint16 x, y;
723    
724          res = res ? lsb_io_uint16(s, &ptr->message) : False;          in_uint16_le(s, message_type);
725          res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;          in_uint8s(s, 2);        /* pad */
726    
727          switch (ptr->message)          switch (message_type)
728          {          {
729                  case RDP_POINTER_MOVE:                  case RDP_POINTER_MOVE:
730                          res = res ? lsb_io_uint16(s, &ptr->x      ) : False;                          in_uint16_le(s, x);
731                          res = res ? lsb_io_uint16(s, &ptr->y      ) : False;                          in_uint16_le(s, y);
732                            if (s_check(s))
733                                    ui_move_pointer(x, y);
734                          break;                          break;
         }  
   
         return res;  
 }  
   
 /* Parse an update PDU */  
 BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  
 {  
         BOOL res = True;  
735    
736          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;                  case RDP_POINTER_COLOR:
737          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;                          process_colour_pointer_pdu(s);
738                            break;
         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);  
   
         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_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);  
739    
740          if (present & 0x08)                  case RDP_POINTER_CACHED:
741                  rdp_io_coord(s, &os->cy, delta);                          process_cached_pointer_pdu(s);
742                            break;
743    
744          if (present & 0x10)                  case RDP_POINTER_SYSTEM:
745                  prs_io_uint8(s, &os->colour);                          process_system_pointer_pdu(s);
746                            break;
747    
748          return PRS_ERROR(s);                  default:
749                            unimpl("Pointer message 0x%x\n", message_type);
750            }
751  }  }
752    
753  /* Parse a desktop save order */  /* Process bitmap updates */
754  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  void
755    process_bitmap_updates(STREAM s)
756  {  {
757          if (present & 0x01)          uint16 num_updates;
758                  lsb_io_uint32(s, &os->offset);          uint16 left, top, right, bottom, width, height;
759            uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
760          if (present & 0x02)          uint8 *data, *bmpdata;
761                  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);  
762    
763          if (present & 0x20)          in_uint16_le(s, num_updates);
                 prs_io_uint8(s, &os->action);  
764    
765          return PRS_ERROR(s);          for (i = 0; i < num_updates; i++)
 }  
   
 /* Parse a memory blt order */  
 BOOL rdp_io_memblt_order(STREAM s, MEMBLT_ORDER *os, uint32 present, BOOL delta)  
 {  
         if (present & 0x0001)  
766          {          {
767                  prs_io_uint8(s, &os->cache_id);                  in_uint16_le(s, left);
768                  prs_io_uint8(s, &os->colour_table);                  in_uint16_le(s, top);
769          }                  in_uint16_le(s, right);
770                    in_uint16_le(s, bottom);
771          if (present & 0x0002)                  in_uint16_le(s, width);
772                  rdp_io_coord(s, &os->x, delta);                  in_uint16_le(s, height);
773                    in_uint16_le(s, bpp);
774          if (present & 0x0004)                  Bpp = (bpp + 7) / 8;
775                  rdp_io_coord(s, &os->y, delta);                  in_uint16_le(s, compress);
776                    in_uint16_le(s, bufsize);
         if (present & 0x0008)  
                 rdp_io_coord(s, &os->cx, delta);  
777    
778          if (present & 0x0010)                  cx = right - left + 1;
779                  rdp_io_coord(s, &os->cy, delta);                  cy = bottom - top + 1;
780    
781          if (present & 0x0020)                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
782                  prs_io_uint8(s, &os->opcode);                         left, top, right, bottom, width, height, Bpp, compress));
783    
784          if (present & 0x0040)                  if (!compress)
785                  rdp_io_coord(s, &os->srcx, delta);                  {
786                            int y;
787          if (present & 0x0080)                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
788                  rdp_io_coord(s, &os->srcy, delta);                          for (y = 0; y < height; y++)
789                            {
790                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
791                                              width * Bpp);
792                            }
793                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
794                            xfree(bmpdata);
795                            continue;
796                    }
797    
         if (present & 0x0100)  
                 lsb_io_uint16(s, &os->cache_idx);  
798    
799          return PRS_ERROR(s);                  if (compress & 0x400)
800  }                  {
801                            size = bufsize;
802                    }
803                    else
804                    {
805                            in_uint8s(s, 2);        /* pad */
806                            in_uint16_le(s, size);
807                            in_uint8s(s, 4);        /* line_size, final_size */
808                    }
809                    in_uint8p(s, data, size);
810                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
811                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
812                    {
813                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
814                    }
815                    else
816                    {
817                            DEBUG_RDP5(("Failed to decompress data\n"));
818                    }
819    
820  /* 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);  
821          }          }
   
         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);  
822  }  }
823    
824  /* Parse a text order */  /* Process a palette update */
825  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  void
826    process_palette(STREAM s)
827  {  {
828          if (present & 0x000001)          COLOURENTRY *entry;
829                  prs_io_uint8(s, &os->font);          COLOURMAP map;
830            HCOLOURMAP hmap;
831          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);  
832    
833          if (present & 0x002000)          in_uint8s(s, 2);        /* pad */
834                  lsb_io_uint16(s, &os->boxbottom);          in_uint16_le(s, map.ncolours);
835            in_uint8s(s, 2);        /* pad */
836    
837          if (present & 0x080000)          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
                 lsb_io_uint16(s, &os->x);  
838    
839          if (present & 0x100000)          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
                 lsb_io_uint16(s, &os->y);  
840    
841          if (present & 0x200000)          for (i = 0; i < map.ncolours; i++)
842          {          {
843                  prs_io_uint8(s, &os->length);                  entry = &map.colours[i];
844                  prs_io_uint8s(s, os->text, os->length);                  in_uint8(s, entry->red);
845                    in_uint8(s, entry->green);
846                    in_uint8(s, entry->blue);
847          }          }
848    
849          return PRS_ERROR(s);          hmap = ui_create_colourmap(&map);
850  }          ui_set_colourmap(hmap);
851    
852            xfree(map.colours);
 /* SECONDARY ORDERS */  
   
 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;  
853  }  }
854    
855  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)  /* Process an update PDU */
856    static void
857    process_update_pdu(STREAM s)
858  {  {
859          BOOL res = True;          uint16 update_type, count;
860    
861          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          in_uint16_le(s, update_type);
         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;  
862    
863          rbo->data = s->data + s->offset;          switch (update_type)
864          s->offset += rbo->bufsize;          {
865                    case RDP_UPDATE_ORDERS:
866                            in_uint8s(s, 2);        /* pad */
867                            in_uint16_le(s, count);
868                            in_uint8s(s, 2);        /* pad */
869                            process_orders(s, count);
870                            break;
871    
872          return res;                  case RDP_UPDATE_BITMAP:
873  }                          process_bitmap_updates(s);
874                            break;
875    
876  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)                  case RDP_UPDATE_PALETTE:
877  {                          process_palette(s);
878          BOOL res = True;                          break;
879    
880          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;                  case RDP_UPDATE_SYNCHRONIZE:
881          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;                          break;
         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;  
882    
883          rbo->data = s->data + s->offset;                  default:
884          s->offset += rbo->size;                          unimpl("update %d\n", update_type);
885            }
886    
         return res;  
887  }  }
888    
889  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process a disconnect PDU */
890    void
891    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
892  {  {
893          COLOURENTRY *entry;          in_uint32_le(s, *ext_disc_reason);
         int i;  
894    
895          prs_io_uint8(s, &colours->cache_id);          DEBUG(("Received disconnect PDU\n"));
         lsb_io_uint16(s, &colours->map.ncolours);  
   
         for (i = 0; i < colours->map.ncolours; i++)  
         {  
                 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++;  
         }  
   
         return True;  
896  }  }
897    
898  BOOL rdp_io_fontcache_order(STREAM s, RDP_FONTCACHE_ORDER *font)  /* Process data PDU */
899    static BOOL
900    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
901  {  {
902          RDP_FONT_GLYPH *glyph;          uint8 data_pdu_type;
903          BOOL res = True;          uint8 ctype;
904          int i, j, datasize;          uint16 clen;
905          uint8 in, out;          int len;
906    #if 0
907            int roff, rlen, ret;
908            static struct stream ns;
909            static signed char *dict = 0;
910    #endif
911    
912          res = res ? prs_io_uint8(s, &font->font   ) : False;          in_uint8s(s, 6);        /* shareid, pad, streamid */
913          res = res ? prs_io_uint8(s, &font->nglyphs) : False;          in_uint16(s, len);
914            in_uint8(s, data_pdu_type);
915            in_uint8(s, ctype);
916            in_uint16(s, clen);
917            clen -= 18;
918    
919          for (i = 0; i < font->nglyphs; i++)  #if 0
920            if (ctype & 0x20)
921          {          {
922                  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++)  
923                  {                  {
924                          in = glyph->data[j];                          dict = (signed char *) malloc(8200 * sizeof(signed char));
925                          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;  
926                  }                  }
         }  
927    
928          return res;                  ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen);
 }  
929    
930                    len -= 18;
931    
932  /* CAPABILITIES */                  ns.data = xrealloc(ns.data, len);
933    
934  /* Construct a general capability set */                  ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len);
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
 {  
         caps->os_major_type = 1;  
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
935    
936  /* Parse general capability set */                  ns.size = len;
937  BOOL rdp_io_general_caps(STREAM s, RDP_GENERAL_CAPS *caps)                  ns.end = ns.data + ns.size;
938  {                  ns.p = ns.data;
939          uint16 length = RDP_CAPLEN_GENERAL;                  ns.rdp_hdr = ns.p;
         uint16 pkt_length = length;  
         BOOL res;  
940    
941          res = lsb_io_uint16(s, &pkt_length);                  s = &ns;
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
942          }          }
943    #endif
944    
945          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          switch (data_pdu_type)
         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;  
   
         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->preferred_bpp) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive1bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive4bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->receive8bpp  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->width        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->height       ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1         ) : False;  
         res = res ? lsb_io_uint16(s, &caps->allow_resize ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compression  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown1     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->unknown2     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2         ) : False;  
   
         return res;  
 }  
   
 /* Construct an order capability set */  
 void rdp_make_order_caps(RDP_ORDER_CAPS *caps)  
 {  
         caps->xgranularity = 1;  
         caps->ygranularity = 20;  
         caps->max_order_level = 1;  
         caps->num_fonts = 0x147;  
         caps->cap_flags = 0x2A;  
   
 //      caps->cap_flags = ORDER_CAP_NEGOTIATE | ORDER_CAP_NOSUPPORT;  
   
         caps->support[0] = caps->support[1] = caps->support[2]  
                 = caps->support[3] = caps->support[4] = caps->support[5]  
                 = caps->support[6] = caps->support[8] = caps->support[11]  
                 = caps->support[12] = caps->support[22] = caps->support[28]  
                 = caps->support[29] = caps->support[30] = 1;  
         caps->text_cap_flags = 0x6A1;  
         caps->desk_save_size = 0x38400;  
         caps->unknown2 = 0x4E4;  
 }  
   
 /* Parse order capability set */  
 BOOL rdp_io_order_caps(STREAM s, RDP_ORDER_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_ORDER;  
         uint16 pkt_length = length;  
         BOOL res;  
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
   
         res = res ? prs_io_uint8s(s,  caps->terminal_desc, 16) : False;  
         res = res ? lsb_io_uint32(s, &caps->pad1             ) : False;  
         res = res ? lsb_io_uint16(s, &caps->xgranularity     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ygranularity     ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2             ) : False;  
         res = res ? lsb_io_uint16(s, &caps->max_order_level  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->num_fonts        ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_flags        ) : False;  
         res = res ? prs_io_uint8s(s,  caps->support      , 32) : False;  
         res = res ? lsb_io_uint16(s, &caps->text_cap_flags   ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->pad4             ) : False;  
         res = res ? lsb_io_uint32(s, &caps->desk_save_size   ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown1         ) : False;  
         res = res ? lsb_io_uint32(s, &caps->unknown2         ) : False;  
   
         return res;  
 }  
   
 /* Construct a bitmap cache capability set */  
 void rdp_make_bmpcache_caps(RDP_BMPCACHE_CAPS *caps)  
 {  
         caps->caches[0].entries = 0x258;  
         caps->caches[0].max_cell_size = 0x100;  
         caps->caches[1].entries = 0x12c;  
         caps->caches[1].max_cell_size = 0x400;  
         caps->caches[2].entries = 0x106;  
         caps->caches[2].max_cell_size = 0x1000;  
 }  
   
 /* 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)  
946          {          {
947                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
948                  return False;                          process_update_pdu(s);
949          }                          break;
   
         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;  
 }  
950    
951  /* Parse control capability set */                  case RDP_DATA_PDU_CONTROL:
952  BOOL rdp_io_control_caps(STREAM s, RDP_CONTROL_CAPS *caps)                          DEBUG(("Received Control PDU\n"));
953  {                          break;
         uint16 length = RDP_CAPLEN_CONTROL;  
         uint16 pkt_length = length;  
         BOOL res;  
954    
955          res = lsb_io_uint16(s, &pkt_length);                  case RDP_DATA_PDU_SYNCHRONISE:
956          if (pkt_length != length)                          DEBUG(("Received Sync PDU\n"));
957          {                          break;
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
958    
959          res = res ? lsb_io_uint16(s, &caps->control_caps    ) : False;                  case RDP_DATA_PDU_POINTER:
960          res = res ? lsb_io_uint16(s, &caps->remote_detach   ) : False;                          process_pointer_pdu(s);
961          res = res ? lsb_io_uint16(s, &caps->control_interest) : False;                          break;
         res = res ? lsb_io_uint16(s, &caps->detach_interest ) : False;  
962    
963          return res;                  case RDP_DATA_PDU_BELL:
964  }                          ui_bell();
965                            break;
966    
967  /* Construct an activation capability set */                  case RDP_DATA_PDU_LOGON:
968  void rdp_make_activate_caps(RDP_ACTIVATE_CAPS *caps)                          DEBUG(("Received Logon PDU\n"));
969  {                          /* User logged on */
970  }                          break;
971    
972  /* Parse activation capability set */                  case RDP_DATA_PDU_DISCONNECT:
973  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)                          process_disconnect_pdu(s, ext_disc_reason);
974  {                          return True;
         uint16 length = RDP_CAPLEN_ACTIVATE;  
         uint16 pkt_length = length;  
         BOOL res;  
975    
976          res = lsb_io_uint16(s, &pkt_length);                  default:
977          if (pkt_length != length)                          unimpl("data PDU %d\n", data_pdu_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
978          }          }
979            return False;
         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;  
980  }  }
981    
982  /* Parse pointer capability set */  /* Process incoming packets */
983  BOOL rdp_io_pointer_caps(STREAM s, RDP_POINTER_CAPS *caps)  void
984    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
985  {  {
986          uint16 length = RDP_CAPLEN_POINTER;          uint8 type;
987          uint16 pkt_length = length;          BOOL disc = False;      /* True when a disconnect PDU was received */
988          BOOL res;          STREAM s;
989    
990          res = lsb_io_uint16(s, &pkt_length);          while ((s = rdp_recv(&type)) != NULL)
         if (pkt_length != length)  
991          {          {
992                  ERROR("Unrecognised capabilities size\n");                  switch (type)
993                  return False;                  {
994          }                          case RDP_PDU_DEMAND_ACTIVE:
995                                    process_demand_active(s);
996                                    *deactivated = False;
997                                    break;
998    
999          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                          case RDP_PDU_DEACTIVATE:
1000          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                                  *deactivated = True;
1001                                    break;
1002    
1003          return res;                          case RDP_PDU_DATA:
1004  }                                  disc = process_data_pdu(s, ext_disc_reason);
1005                                    break;
1006    
1007  /* Construct a share capability set */                          case 0:
1008  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)                                  break;
 {  
 }  
1009    
1010  /* Parse share capability set */                          default:
1011  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                                  unimpl("PDU %d\n", type);
1012  {                  }
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
1013    
1014          res = lsb_io_uint16(s, &pkt_length);                  if (disc)
1015          if (pkt_length != length)                  {
1016          {                          return;
1017                  ERROR("Unrecognised capabilities size\n");                  }
                 return False;  
1018          }          }
1019            return;
         res = res ? lsb_io_uint16(s, &caps->userid) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad   ) : False;  
   
         return res;  
1020  }  }
1021    
1022  /* Construct a colour cache capability set */  /* Establish a connection up to the RDP layer */
1023  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  BOOL
1024  {  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1025          caps->cache_size = 6;              char *command, char *directory)
 }  
   
 /* Parse colour cache capability set */  
 BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  
1026  {  {
1027          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");  
1028                  return False;                  return False;
         }  
   
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
1029    
1030          return res;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1031            return True;
1032  }  }
1033    
1034  uint8 canned_caps[] = {  /* Disconnect from the RDP layer */
1035  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  void
1036  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)  
1037  {  {
1038          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;  
1039  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26