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

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

  ViewVC Help
Powered by ViewVC 1.1.26