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

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

  ViewVC Help
Powered by ViewVC 1.1.26