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

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

  ViewVC Help
Powered by ViewVC 1.1.26