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

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

  ViewVC Help
Powered by ViewVC 1.1.26