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

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

  ViewVC Help
Powered by ViewVC 1.1.26