/[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 907 by jdmeijer, Tue May 31 18:49:05 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  BOOL rdp_io_colour(STREAM s, uint8 *colour)                          4 +     /* flags */
327  {                          2 +     /* len_domain */
328          BOOL res;                          2 +     /* len_user */
329                            (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
330          res = prs_io_uint8(s, colour);                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
331          s->offset += 2;                          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          return res;                  }
360  }                  if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
361                    {
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  BOOL rdp_io_colourmap(STREAM s, COLOURMAP *colours)                  }
384  {                  else
385          int datasize;                  {
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          lsb_io_uint16(s, &colours->ncolours);                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
403          datasize = colours->ncolours * 3;                  out_uint32_le(s, tzone);
404    
405          if (datasize > sizeof(colours->colours))                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
406                  return False;                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
407    
408          memcpy(colours->colours, s->data + s->offset, datasize);                  out_uint32_le(s, 0x0a0000);
409          s->offset += datasize;                  out_uint32_le(s, 0x050000);
410          return True;                  out_uint32_le(s, 3);
411  }                  out_uint32_le(s, 0);
412                    out_uint32_le(s, 0);
413    
414  BOOL rdp_io_bounds(STREAM s, BOUNDS *bounds)                  rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
415  {                  out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
         uint8 present;  
416    
417          prs_io_uint8(s, &present);                  out_uint32_le(s, 0x30000);
418                    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    
         if (present & 1)  
                 rdp_io_coord(s, &bounds->left, False);  
         else if (present & 16)  
                 rdp_io_coord(s, &bounds->left, True);  
   
         if (present & 2)  
                 rdp_io_coord(s, &bounds->top, False);  
         else if (present & 32)  
                 rdp_io_coord(s, &bounds->top, True);  
   
         if (present & 4)  
                 rdp_io_coord(s, &bounds->right, False);  
         else if (present & 64)  
                 rdp_io_coord(s, &bounds->right, True);  
   
         if (present & 8)  
                 rdp_io_coord(s, &bounds->bottom, False);  
         else if (present & 128)  
                 rdp_io_coord(s, &bounds->bottom, True);  
426    
427          return True;          }
428            s_mark_end(s);
429            sec_send(s, sec_flags);
430  }  }
431    
432  BOOL rdp_io_pen(STREAM s, PEN *pen, uint32 present)  /* Send a control PDU */
433    static void
434    rdp_send_control(uint16 action)
435  {  {
436          BOOL res = True;          STREAM s;
437    
438          if (present & 1)          s = rdp_init_data(8);
                 res = res ? prs_io_uint8(s, &pen->style) : False;  
439    
440          if (present & 2)          out_uint16_le(s, action);
441                  res = res ? prs_io_uint8(s, &pen->width) : False;          out_uint16(s, 0);       /* userid */
442            out_uint32(s, 0);       /* control id */
443    
444          if (present & 4)          s_mark_end(s);
445                  res = res ? rdp_io_colour(s, &pen->colour) : False;          rdp_send_data(s, RDP_DATA_PDU_CONTROL);
   
         return res;  
446  }  }
447    
448  BOOL rdp_io_brush(STREAM s, BRUSH *brush, 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, &brush->xorigin) : False;  
453    
454          if (present & 2)          s = rdp_init_data(4);
                 res = res ? prs_io_uint8(s, &brush->yorigin) : False;  
455    
456          if (present & 4)          out_uint16_le(s, 1);    /* type */
457                  res = res ? prs_io_uint8(s, &brush->style) : False;          out_uint16_le(s, 1002);
458    
459          if (present & 8)          s_mark_end(s);
460                  res = res ? prs_io_uint8(s, &brush->pattern[0]) : False;          rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
   
         if (present & 16)  
                 res = res ? prs_io_uint8s(s, &brush->pattern[1], 7) : False;  
   
         return res;  
461  }  }
462    
463  /* Construct a confirm/demand active PDU */  /* Send a single input event */
464  void rdp_make_active_pdu(RDP_ACTIVE_PDU *pdu, uint32 shareid, uint16 userid,  void
465                                  int width, int height)  rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
466  {  {
467          memset(pdu, 0, sizeof(*pdu));          STREAM s;
468          pdu->shareid = shareid;  
469          pdu->userid  = 1002;          s = rdp_init_data(16);
         pdu->source_len = sizeof(RDP_SOURCE);  
         memcpy(pdu->source, RDP_SOURCE, sizeof(RDP_SOURCE));  
470    
471          pdu->caps_len = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          out_uint16_le(s, 1);    /* number of events */
472                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          out_uint16(s, 0);       /* pad */
                 + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE  
                 + RDP_CAPLEN_UNKNOWN;  
         pdu->num_caps = 0xD;  
473    
474          rdp_make_general_caps (&pdu->general_caps );          out_uint32_le(s, time);
475          rdp_make_bitmap_caps  (&pdu->bitmap_caps, width, height);          out_uint16_le(s, message_type);
476          rdp_make_order_caps   (&pdu->order_caps   );          out_uint16_le(s, device_flags);
477          rdp_make_bmpcache_caps(&pdu->bmpcache_caps);          out_uint16_le(s, param1);
478          rdp_make_control_caps (&pdu->control_caps );          out_uint16_le(s, param2);
479          rdp_make_activate_caps(&pdu->activate_caps);  
480          rdp_make_pointer_caps (&pdu->pointer_caps );          s_mark_end(s);
481          rdp_make_share_caps   (&pdu->share_caps, userid);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
         rdp_make_colcache_caps(&pdu->colcache_caps);  
482  }  }
483    
484  /* Parse a confirm/demand active PDU */  /* Send a client window information PDU */
485  BOOL rdp_io_active_pdu(STREAM s, RDP_ACTIVE_PDU *pdu, int pdutype)  void
486    rdp_send_client_window_status(int status)
487  {  {
488          uint16 capset;          STREAM s;
489          uint16 length;          static int current_status = 1;
         BOOL res;  
         int i;  
490    
491          res = lsb_io_uint32(s, &pdu->shareid);          if (current_status == status)
492                    return;
493    
494          if (pdutype == RDP_PDU_CONFIRM_ACTIVE)          s = rdp_init_data(12);
                 res = res ? lsb_io_uint16(s, &pdu->userid    ) : False;  
495    
496          res = res ? lsb_io_uint16(s, &pdu->source_len) : False;          out_uint32_le(s, status);
         res = res ? lsb_io_uint16(s, &pdu->caps_len  ) : False;  
497    
498          if (pdu->source_len > 48)          switch (status)
499          {          {
500                  ERROR("RDP source descriptor too long\n");                  case 0: /* shut the server up */
501                  return False;                          break;
502    
503                    case 1: /* receive data again */
504                            out_uint32_le(s, 0);    /* unknown */
505                            out_uint16_le(s, g_width);
506                            out_uint16_le(s, g_height);
507                            break;
508          }          }
509    
510          res = res ? prs_io_uint8s(s,  pdu->source, pdu->source_len) : False;          s_mark_end(s);
511          res = res ? lsb_io_uint16(s, &pdu->num_caps  ) : False;          rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
512          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;          current_status = status;
513    }
514          if (s->marshall)  
515          {  /* Send persistent bitmap cache enumeration PDU's */
516                  capset = RDP_CAPSET_GENERAL;  static void
517                  res = res ? lsb_io_uint16(s, &capset) : False;  rdp_enum_bmpcache2(void)
518                  res = res ? rdp_io_general_caps(s, &pdu->general_caps) : False;  {
519            STREAM s;
520                  capset = RDP_CAPSET_BITMAP;          HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
521                  res = res ? lsb_io_uint16(s, &capset) : False;          uint32 num_keys, offset, count, flags;
522                  res = res ? rdp_io_bitmap_caps (s, &pdu->bitmap_caps ) : False;  
523            offset = 0;
524                  capset = RDP_CAPSET_ORDER;          num_keys = pstcache_enumerate(2, keylist);
525                  res = res ? lsb_io_uint16(s, &capset) : False;  
526                  res = res ? rdp_io_order_caps  (s, &pdu->order_caps  ) : False;          while (offset < num_keys)
527            {
528                  capset = RDP_CAPSET_BMPCACHE;                  count = MIN(num_keys - offset, 169);
529                  res = res ? lsb_io_uint16(s, &capset) : False;  
530                  res = res ? rdp_io_bmpcache_caps(s, &pdu->bmpcache_caps) : False;                  s = rdp_init_data(24 + count * sizeof(HASH_KEY));
531    
532                  capset = RDP_CAPSET_COLCACHE;                  flags = 0;
533                  res = res ? lsb_io_uint16(s, &capset) : False;                  if (offset == 0)
534                  res = res ? rdp_io_colcache_caps(s, &pdu->colcache_caps) : False;                          flags |= PDU_FLAG_FIRST;
535                    if (num_keys - offset <= 169)
536                  capset = RDP_CAPSET_ACTIVATE;                          flags |= PDU_FLAG_LAST;
537                  res = res ? lsb_io_uint16(s, &capset) : False;  
538                  res = res ? rdp_io_activate_caps(s, &pdu->activate_caps) : False;                  /* header */
539                    out_uint32_le(s, 0);
540                  capset = RDP_CAPSET_CONTROL;                  out_uint16_le(s, count);
541                  res = res ? lsb_io_uint16(s, &capset) : False;                  out_uint16_le(s, 0);
542                  res = res ? rdp_io_control_caps(s, &pdu->control_caps) : False;                  out_uint16_le(s, 0);
543                    out_uint16_le(s, 0);
544                  capset = RDP_CAPSET_POINTER;                  out_uint16_le(s, 0);
545                  res = res ? lsb_io_uint16(s, &capset) : False;                  out_uint16_le(s, num_keys);
546                  res = res ? rdp_io_pointer_caps(s, &pdu->pointer_caps) : False;                  out_uint32_le(s, 0);
547                    out_uint32_le(s, flags);
548                  capset = RDP_CAPSET_SHARE;  
549                  res = res ? lsb_io_uint16(s, &capset) : False;                  /* list */
550                  res = res ? rdp_io_share_caps  (s, &pdu->share_caps  ) : False;                  out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
551    
552                  capset = RDP_CAPSET_UNKNOWN;                  s_mark_end(s);
553                  res = res ? lsb_io_uint16(s, &capset) : False;                  rdp_send_data(s, 0x2b);
554                  res = res ? rdp_io_unknown_caps(s, NULL) : False;  
555                    offset += 169;
556            }
557    }
558    
559    /* Send an (empty) font information PDU */
560    static void
561    rdp_send_fonts(uint16 seq)
562    {
563            STREAM s;
564    
565            s = rdp_init_data(8);
566    
567            out_uint16(s, 0);       /* number of fonts */
568            out_uint16_le(s, 0);    /* pad? */
569            out_uint16_le(s, seq);  /* unknown */
570            out_uint16_le(s, 0x32); /* entry size */
571    
572            s_mark_end(s);
573            rdp_send_data(s, RDP_DATA_PDU_FONT2);
574    }
575    
576    /* Output general capability set */
577    static void
578    rdp_out_general_caps(STREAM s)
579    {
580            out_uint16_le(s, RDP_CAPSET_GENERAL);
581            out_uint16_le(s, RDP_CAPLEN_GENERAL);
582    
583            out_uint16_le(s, 1);    /* OS major type */
584            out_uint16_le(s, 3);    /* OS minor type */
585            out_uint16_le(s, 0x200);        /* Protocol version */
586            out_uint16(s, 0);       /* Pad */
587            out_uint16(s, 0);       /* Compression types */
588            out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
589            /* Pad, according to T.128. 0x40d seems to
590               trigger
591               the server to start sending RDP5 packets.
592               However, the value is 0x1d04 with W2KTSK and
593               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
594               for sending such information in a padding
595               field.. */
596            out_uint16(s, 0);       /* Update capability */
597            out_uint16(s, 0);       /* Remote unshare capability */
598            out_uint16(s, 0);       /* Compression level */
599            out_uint16(s, 0);       /* Pad */
600    }
601    
602    /* Output bitmap capability set */
603    static void
604    rdp_out_bitmap_caps(STREAM s)
605    {
606            out_uint16_le(s, RDP_CAPSET_BITMAP);
607            out_uint16_le(s, RDP_CAPLEN_BITMAP);
608    
609            out_uint16_le(s, g_server_bpp); /* Preferred BPP */
610            out_uint16_le(s, 1);    /* Receive 1 BPP */
611            out_uint16_le(s, 1);    /* Receive 4 BPP */
612            out_uint16_le(s, 1);    /* Receive 8 BPP */
613            out_uint16_le(s, 800);  /* Desktop width */
614            out_uint16_le(s, 600);  /* Desktop height */
615            out_uint16(s, 0);       /* Pad */
616            out_uint16(s, 1);       /* Allow resize */
617            out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
618            out_uint16(s, 0);       /* Unknown */
619            out_uint16_le(s, 1);    /* Unknown */
620            out_uint16(s, 0);       /* Pad */
621    }
622    
623    /* Output order capability set */
624    static void
625    rdp_out_order_caps(STREAM s)
626    {
627            uint8 order_caps[32];
628    
629            memset(order_caps, 0, 32);
630            order_caps[0] = 1;      /* dest blt */
631            order_caps[1] = 1;      /* pat blt */
632            order_caps[2] = 1;      /* screen blt */
633            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
634            order_caps[4] = 0;      /* triblt */
635            order_caps[8] = 1;      /* line */
636            order_caps[9] = 1;      /* line */
637            order_caps[10] = 1;     /* rect */
638            order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
639            order_caps[13] = 1;     /* memblt */
640            order_caps[14] = 1;     /* triblt */
641            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
642            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
643            order_caps[22] = 1;     /* polyline */
644            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
645            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
646            order_caps[27] = 1;     /* text2 */
647            out_uint16_le(s, RDP_CAPSET_ORDER);
648            out_uint16_le(s, RDP_CAPLEN_ORDER);
649    
650            out_uint8s(s, 20);      /* Terminal desc, pad */
651            out_uint16_le(s, 1);    /* Cache X granularity */
652            out_uint16_le(s, 20);   /* Cache Y granularity */
653            out_uint16(s, 0);       /* Pad */
654            out_uint16_le(s, 1);    /* Max order level */
655            out_uint16_le(s, 0x147);        /* Number of fonts */
656            out_uint16_le(s, 0x2a); /* Capability flags */
657            out_uint8p(s, order_caps, 32);  /* Orders supported */
658            out_uint16_le(s, 0x6a1);        /* Text capability flags */
659            out_uint8s(s, 6);       /* Pad */
660            out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
661            out_uint32(s, 0);       /* Unknown */
662            out_uint32_le(s, 0x4e4);        /* Unknown */
663    }
664    
665    /* Output bitmap cache capability set */
666    static void
667    rdp_out_bmpcache_caps(STREAM s)
668    {
669            int Bpp;
670            out_uint16_le(s, RDP_CAPSET_BMPCACHE);
671            out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
672    
673            Bpp = (g_server_bpp + 7) / 8;
674            out_uint8s(s, 24);      /* unused */
675            out_uint16_le(s, 0x258);        /* entries */
676            out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
677            out_uint16_le(s, 0x12c);        /* entries */
678            out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
679            out_uint16_le(s, 0x106);        /* entries */
680            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
681    }
682    
683    /* Output bitmap cache v2 capability set */
684    static void
685    rdp_out_bmpcache2_caps(STREAM s)
686    {
687            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
688            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
689    
690            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
691    
692            out_uint16_be(s, 3);    /* number of caches in this set */
693    
694            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
695            out_uint32_le(s, BMPCACHE2_C0_CELLS);
696            out_uint32_le(s, BMPCACHE2_C1_CELLS);
697            if (pstcache_init(2))
698            {
699                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
700          }          }
701          else          else
702          {          {
703                  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);  
                         }  
                 }  
704          }          }
705            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;  
706  }  }
707    
708  /* Parse a control PDU */  /* Output control capability set */
709  BOOL rdp_io_control_pdu(STREAM s, RDP_CONTROL_PDU *pdu)  static void
710    rdp_out_control_caps(STREAM s)
711  {  {
712          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_CONTROL);
713            out_uint16_le(s, RDP_CAPLEN_CONTROL);
714    
715          res = res ? lsb_io_uint16(s, &pdu->action   ) : False;          out_uint16(s, 0);       /* Control capabilities */
716          res = res ? lsb_io_uint16(s, &pdu->userid   ) : False;          out_uint16(s, 0);       /* Remote detach */
717          res = res ? lsb_io_uint32(s, &pdu->controlid) : False;          out_uint16_le(s, 2);    /* Control interest */
718            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;  
719  }  }
720    
721  /* Parse a synchronisation PDU */  /* Output activation capability set */
722  BOOL rdp_io_synchronise_pdu(STREAM s, RDP_SYNCHRONISE_PDU *pdu)  static void
723    rdp_out_activate_caps(STREAM s)
724  {  {
725          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
726            out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
727    
728          res = res ? lsb_io_uint16(s, &pdu->type  ) : False;          out_uint16(s, 0);       /* Help key */
729          res = res ? lsb_io_uint16(s, &pdu->userid) : False;          out_uint16(s, 0);       /* Help index key */
730            out_uint16(s, 0);       /* Extended help key */
731          return res;          out_uint16(s, 0);       /* Window activate */
732  }  }
733    
734  /* Parse a single input event */  /* Output pointer capability set */
735  BOOL rdp_io_input_event(STREAM s, RDP_INPUT_EVENT *evt)  static void
736    rdp_out_pointer_caps(STREAM s)
737  {  {
738          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_POINTER);
739            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;  
740    
741          if (!res)          out_uint16(s, 0);       /* Colour pointer */
742                  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;  
743  }  }
744    
745  /* Construct an input PDU */  /* Output share capability set */
746  void rdp_make_input_pdu(RDP_INPUT_PDU *pdu, uint16 message_type,  static void
747                          uint16 device_flags, uint16 param1, uint16 param2)  rdp_out_share_caps(STREAM s)
748  {  {
749          uint32 now = time(NULL);          out_uint16_le(s, RDP_CAPSET_SHARE);
750            out_uint16_le(s, RDP_CAPLEN_SHARE);
         pdu->num_events = 1;  
         pdu->pad = 0;  
751    
752          pdu->event[0].event_time = now;          out_uint16(s, 0);       /* userid */
753          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;  
754  }  }
755    
756  /* Parse an input PDU */  /* Output colour cache capability set */
757  BOOL rdp_io_input_pdu(STREAM s, RDP_INPUT_PDU *pdu)  static void
758    rdp_out_colcache_caps(STREAM s)
759  {  {
760          BOOL res = True;          out_uint16_le(s, RDP_CAPSET_COLCACHE);
761          int i;          out_uint16_le(s, RDP_CAPLEN_COLCACHE);
762    
763          res = res ? lsb_io_uint16(s, &pdu->num_events) : False;          out_uint16_le(s, 6);    /* cache size */
764          res = res ? lsb_io_uint16(s, &pdu->pad       ) : False;          out_uint16(s, 0);       /* pad */
765    }
766    
767          if (pdu->num_events > RDP_MAX_EVENTS)  static uint8 caps_0x0d[] = {
768          {          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
769                  ERROR("Too many events in one PDU\n");          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770                  return False;          0x0C, 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, 0x00, 0x00, 0x00, 0x00,
774            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778            0x00, 0x00, 0x00, 0x00
779    };
780    
781          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;  
         }  
782    
783          return res;  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
 }  
784    
785  /* Construct a font information PDU */  static uint8 caps_0x10[] = {
786  void rdp_make_font_pdu(RDP_FONT_PDU *pdu, uint16 seqno)          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
787  {          0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
788          pdu->num_fonts = 0;          0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
789          pdu->unknown1 = 0x3e;          0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
790          pdu->unknown2 = seqno;          0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
791          pdu->entry_size = RDP_FONT_INFO_SIZE;          0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
792  }  };
793    
794  /* Parse a font information structure */  /* Output unknown capability sets */
795  BOOL rdp_io_font_info(STREAM s, RDP_FONT_INFO *font)  static void
796    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
797  {  {
798          BOOL res = True;          out_uint16_le(s, id);
799            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;  
800    
801          return res;          out_uint8p(s, caps, length - 4);
802  }  }
803    
804  /* Parse a font information PDU */  #define RDP5_FLAG 0x0030
805  BOOL rdp_io_font_pdu(STREAM s, RDP_FONT_PDU *pdu)  /* Send a confirm active PDU */
806    static void
807    rdp_send_confirm_active(void)
808  {  {
809          BOOL res = True;          STREAM s;
810          int i;          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
811            uint16 caplen =
812          res = res ? lsb_io_uint16(s, &pdu->num_fonts ) : False;                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
813          res = res ? lsb_io_uint16(s, &pdu->unknown1  ) : False;                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
814          res = res ? lsb_io_uint16(s, &pdu->unknown2  ) : False;                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
815          res = res ? lsb_io_uint16(s, &pdu->entry_size) : False;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
816                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
817                    4 /* w2k fix, why? */ ;
818    
819          if (pdu->num_fonts > RDP_MAX_FONTS)          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
         {  
                 ERROR("Too many fonts in one PDU\n");  
                 return False;  
         }  
820    
821          for (i = 0; i < pdu->num_fonts; i++)          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
822          {          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
823                  res = res ? rdp_io_font_info(s, &pdu->font[i]) : False;          out_uint16_le(s, (g_mcs_userid + 1001));
         }  
824    
825          return res;          out_uint32_le(s, g_rdp_shareid);
826  }          out_uint16_le(s, 0x3ea);        /* userid */
827            out_uint16_le(s, sizeof(RDP_SOURCE));
828            out_uint16_le(s, caplen);
829    
830  /* Parse a pointer PDU */          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
831  BOOL rdp_io_pointer_pdu(STREAM s, RDP_POINTER_PDU *ptr)          out_uint16_le(s, 0xd);  /* num_caps */
832  {          out_uint8s(s, 2);       /* pad */
         BOOL res = True;  
833    
834          res = res ? lsb_io_uint16(s, &ptr->message) : False;          rdp_out_general_caps(s);
835          res = res ? lsb_io_uint16(s, &ptr->pad    ) : False;          rdp_out_bitmap_caps(s);
836            rdp_out_order_caps(s);
837            g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
838            rdp_out_colcache_caps(s);
839            rdp_out_activate_caps(s);
840            rdp_out_control_caps(s);
841            rdp_out_pointer_caps(s);
842            rdp_out_share_caps(s);
843    
844          switch (ptr->message)          rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
845          {          rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
846                  case RDP_POINTER_MOVE:          rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
847                          res = res ? lsb_io_uint16(s, &ptr->x      ) : False;          rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
                         res = res ? lsb_io_uint16(s, &ptr->y      ) : False;  
                         break;  
         }  
848    
849          return res;          s_mark_end(s);
850            sec_send(s, sec_flags);
851  }  }
852    
853  /* Parse an update PDU */  /* Process a general capability set */
854  BOOL rdp_io_update_pdu(STREAM s, RDP_UPDATE_PDU *pdu)  static void
855    rdp_process_general_caps(STREAM s)
856  {  {
857          BOOL res = True;          uint16 pad2octetsB;     /* rdp5 flags? */
858    
859          res = res ? lsb_io_uint16(s, &pdu->update_type) : False;          in_uint8s(s, 10);
860          res = res ? lsb_io_uint16(s, &pdu->pad        ) : False;          in_uint16_le(s, pad2octetsB);
861    
862          return res;          if (!pad2octetsB)
863                    g_use_rdp5 = False;
864  }  }
865    
866    /* Process a bitmap capability set */
867  /* PRIMARY ORDERS */  static void
868    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)  
869  {  {
870          if (present & 0x01)          uint16 width, height, bpp;
                 rdp_io_coord(s, &os->x, delta);  
   
         if (present & 0x02)  
                 rdp_io_coord(s, &os->y, delta);  
871    
872          if (present & 0x04)          in_uint16_le(s, bpp);
873                  rdp_io_coord(s, &os->cx, delta);          in_uint8s(s, 6);
874    
875          if (present & 0x08)          in_uint16_le(s, width);
876                  rdp_io_coord(s, &os->cy, delta);          in_uint16_le(s, height);
877    
878          if (present & 0x10)          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
                 prs_io_uint8(s, &os->opcode);  
879    
880          return PRS_ERROR(s);          /*
881             * The server may limit bpp and change the size of the desktop (for
882             * example when shadowing another session).
883             */
884            if (g_server_bpp != bpp)
885            {
886                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
887                    g_server_bpp = bpp;
888            }
889            if (g_width != width || g_height != height)
890            {
891                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
892                            width, height);
893                    g_width = width;
894                    g_height = height;
895                    ui_resize_window();
896            }
897  }  }
898    
899  /* Parse an pattern blt order */  /* Process server capabilities */
900  BOOL rdp_io_patblt_order(STREAM s, PATBLT_ORDER *os, uint32 present, BOOL delta)  void
901    rdp_process_server_caps(STREAM s, uint16 length)
902  {  {
903          if (present & 0x0001)          int n;
904                  rdp_io_coord(s, &os->x, delta);          uint8 *next, *start;
905            uint16 ncapsets, capset_type, capset_length;
906    
907          if (present & 0x0002)          start = s->p;
                 rdp_io_coord(s, &os->y, delta);  
908    
909          if (present & 0x0004)          in_uint16_le(s, ncapsets);
910                  rdp_io_coord(s, &os->cx, delta);          in_uint8s(s, 2);        /* pad */
911    
912          if (present & 0x0008)          for (n = 0; n < ncapsets; n++)
913                  rdp_io_coord(s, &os->cy, delta);          {
914                    if (s->p > start + length)
915                            return;
916    
917          if (present & 0x0010)                  in_uint16_le(s, capset_type);
918                  prs_io_uint8(s, &os->opcode);                  in_uint16_le(s, capset_length);
919    
920          if (present & 0x0020)                  next = s->p + capset_length - 4;
                 rdp_io_colour(s, &os->bgcolour);  
921    
922          if (present & 0x0040)                  switch (capset_type)
923                  rdp_io_colour(s, &os->fgcolour);                  {
924                            case RDP_CAPSET_GENERAL:
925                                    rdp_process_general_caps(s);
926                                    break;
927    
928          rdp_io_brush(s, &os->brush, present >> 7);                          case RDP_CAPSET_BITMAP:
929                                    rdp_process_bitmap_caps(s);
930                                    break;
931                    }
932    
933          return PRS_ERROR(s);                  s->p = next;
934            }
935  }  }
936    
937  /* Parse an screen blt order */  /* Respond to a demand active PDU */
938  BOOL rdp_io_screenblt_order(STREAM s, SCREENBLT_ORDER *os, uint32 present, BOOL delta)  static void
939    process_demand_active(STREAM s)
940  {  {
941          if (present & 0x0001)          uint8 type;
942                  rdp_io_coord(s, &os->x, delta);          uint16 len_src_descriptor, len_combined_caps;
   
         if (present & 0x0002)  
                 rdp_io_coord(s, &os->y, delta);  
943    
944          if (present & 0x0004)          in_uint32_le(s, g_rdp_shareid);
945                  rdp_io_coord(s, &os->cx, delta);          in_uint16_le(s, len_src_descriptor);
946            in_uint16_le(s, len_combined_caps);
947            in_uint8s(s, len_src_descriptor);
948    
949          if (present & 0x0008)          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
950                  rdp_io_coord(s, &os->cy, delta);          rdp_process_server_caps(s, len_combined_caps);
951    
952          if (present & 0x0010)          rdp_send_confirm_active();
953                  prs_io_uint8(s, &os->opcode);          rdp_send_synchronise();
954            rdp_send_control(RDP_CTL_COOPERATE);
955            rdp_send_control(RDP_CTL_REQUEST_CONTROL);
956            rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
957            rdp_recv(&type);        /* RDP_CTL_COOPERATE */
958            rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
959            rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
960    
961          if (present & 0x0020)          if (g_use_rdp5)
962                  rdp_io_coord(s, &os->srcx, delta);          {
963                    rdp_enum_bmpcache2();
964          if (present & 0x0040)                  rdp_send_fonts(3);
965                  rdp_io_coord(s, &os->srcy, delta);          }
966            else
967            {
968                    rdp_send_fonts(1);
969                    rdp_send_fonts(2);
970            }
971    
972          return PRS_ERROR(s);          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
973            reset_order_state();
974  }  }
975    
976  /* Parse a line order */  /* Process a colour pointer PDU */
977  BOOL rdp_io_line_order(STREAM s, LINE_ORDER *os, uint32 present, BOOL delta)  void
978    process_colour_pointer_pdu(STREAM s)
979  {  {
980          if (present & 0x0001)          uint16 x, y, width, height, cache_idx, masklen, datalen;
981                  lsb_io_uint16(s, &os->mixmode);          uint8 *mask, *data;
982            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);  
983    
984          if (present & 0x0010)          in_uint16_le(s, cache_idx);
985                  rdp_io_coord(s, &os->endy, delta);          in_uint16_le(s, x);
986            in_uint16_le(s, y);
987          if (present & 0x0020)          in_uint16_le(s, width);
988                  rdp_io_colour(s, &os->bgcolour);          in_uint16_le(s, height);
989            in_uint16_le(s, masklen);
990          if (present & 0x0040)          in_uint16_le(s, datalen);
991                  prs_io_uint8(s, &os->opcode);          in_uint8p(s, data, datalen);
992            in_uint8p(s, mask, masklen);
993          rdp_io_pen(s, &os->pen, present >> 7);          cursor = ui_create_cursor(x, y, width, height, mask, data);
994            ui_set_cursor(cursor);
995          return PRS_ERROR(s);          cache_put_cursor(cache_idx, cursor);
996  }  }
997    
998  /* Parse an opaque rectangle order */  /* Process a cached pointer PDU */
999  BOOL rdp_io_rect_order(STREAM s, RECT_ORDER *os, uint32 present, BOOL delta)  void
1000    process_cached_pointer_pdu(STREAM s)
1001  {  {
1002          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);  
1003    
1004          if (present & 0x10)          in_uint16_le(s, cache_idx);
1005                  prs_io_uint8(s, &os->colour);          ui_set_cursor(cache_get_cursor(cache_idx));
   
         return PRS_ERROR(s);  
1006  }  }
1007    
1008  /* Parse a desktop save order */  /* Process a system pointer PDU */
1009  BOOL rdp_io_desksave_order(STREAM s, DESKSAVE_ORDER *os, uint32 present, BOOL delta)  void
1010    process_system_pointer_pdu(STREAM s)
1011  {  {
1012          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);  
1013    
1014          return PRS_ERROR(s);          in_uint16(s, system_pointer_type);
1015  }          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)  
1016          {          {
1017                  prs_io_uint8(s, &os->cache_id);                  case RDP_NULL_POINTER:
1018                  prs_io_uint8(s, &os->colour_table);                          ui_set_null_cursor();
1019          }                          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);  
 }  
1020    
1021  /* Parse a 3-way blt order */                  default:
1022  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);  
1023          }          }
   
         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);  
1024  }  }
1025    
1026  /* Parse a text order */  /* Process a pointer PDU */
1027  BOOL rdp_io_text2_order(STREAM s, TEXT2_ORDER *os, uint32 present, BOOL delta)  static void
1028    process_pointer_pdu(STREAM s)
1029  {  {
1030          if (present & 0x000001)          uint16 message_type;
1031                  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);  
1032    
1033          if (present & 0x000400)          in_uint16_le(s, message_type);
1034                  lsb_io_uint16(s, &os->boxleft);          in_uint8s(s, 2);        /* pad */
1035    
1036          if (present & 0x000800)          switch (message_type)
1037                  lsb_io_uint16(s, &os->boxtop);          {
1038                    case RDP_POINTER_MOVE:
1039          if (present & 0x001000)                          in_uint16_le(s, x);
1040                  lsb_io_uint16(s, &os->boxright);                          in_uint16_le(s, y);
1041                            if (s_check(s))
1042                                    ui_move_pointer(x, y);
1043                            break;
1044    
1045          if (present & 0x002000)                  case RDP_POINTER_COLOR:
1046                  lsb_io_uint16(s, &os->boxbottom);                          process_colour_pointer_pdu(s);
1047                            break;
1048    
1049          if (present & 0x080000)                  case RDP_POINTER_CACHED:
1050                  lsb_io_uint16(s, &os->x);                          process_cached_pointer_pdu(s);
1051                            break;
1052    
1053          if (present & 0x100000)                  case RDP_POINTER_SYSTEM:
1054                  lsb_io_uint16(s, &os->y);                          process_system_pointer_pdu(s);
1055                            break;
1056    
1057          if (present & 0x200000)                  default:
1058          {                          unimpl("Pointer message 0x%x\n", message_type);
                 prs_io_uint8(s, &os->length);  
                 prs_io_uint8s(s, os->text, os->length);  
1059          }          }
   
         return PRS_ERROR(s);  
1060  }  }
1061    
1062    /* Process bitmap updates */
1063  /* SECONDARY ORDERS */  void
1064    process_bitmap_updates(STREAM s)
 BOOL rdp_io_secondary_order(STREAM s, RDP_SECONDARY_ORDER *rso)  
1065  {  {
1066          BOOL res = True;          uint16 num_updates;
1067            uint16 left, top, right, bottom, width, height;
1068          res = res ? lsb_io_uint16(s, &rso->length) : False;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1069          res = res ? lsb_io_uint16(s, &rso->flags ) : False;          uint8 *data, *bmpdata;
1070          res = res ? prs_io_uint8 (s, &rso->type  ) : False;          int i;
   
         return res;  
 }  
1071    
1072  BOOL rdp_io_raw_bmpcache_order(STREAM s, RDP_RAW_BMPCACHE_ORDER *rbo)          in_uint16_le(s, num_updates);
 {  
         BOOL res = True;  
1073    
1074          res = res ? prs_io_uint8 (s, &rbo->cache_id  ) : False;          for (i = 0; i < num_updates; i++)
1075          res = res ? prs_io_uint8 (s, &rbo->pad1      ) : False;          {
1076          res = res ? prs_io_uint8 (s, &rbo->width     ) : False;                  in_uint16_le(s, left);
1077          res = res ? prs_io_uint8 (s, &rbo->height    ) : False;                  in_uint16_le(s, top);
1078          res = res ? prs_io_uint8 (s, &rbo->bpp       ) : False;                  in_uint16_le(s, right);
1079          res = res ? lsb_io_uint16(s, &rbo->bufsize   ) : False;                  in_uint16_le(s, bottom);
1080          res = res ? lsb_io_uint16(s, &rbo->cache_idx ) : False;                  in_uint16_le(s, width);
1081                    in_uint16_le(s, height);
1082                    in_uint16_le(s, bpp);
1083                    Bpp = (bpp + 7) / 8;
1084                    in_uint16_le(s, compress);
1085                    in_uint16_le(s, bufsize);
1086    
1087          rbo->data = s->data + s->offset;                  cx = right - left + 1;
1088          s->offset += rbo->bufsize;                  cy = bottom - top + 1;
1089    
1090          return res;                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1091  }                         left, top, right, bottom, width, height, Bpp, compress));
1092    
1093  BOOL rdp_io_bmpcache_order(STREAM s, RDP_BMPCACHE_ORDER *rbo)                  if (!compress)
1094  {                  {
1095          BOOL res = True;                          int y;
1096                            bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1097                            for (y = 0; y < height; y++)
1098                            {
1099                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1100                                              width * Bpp);
1101                            }
1102                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1103                            xfree(bmpdata);
1104                            continue;
1105                    }
1106    
         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;  
1107    
1108          rbo->data = s->data + s->offset;                  if (compress & 0x400)
1109          s->offset += rbo->size;                  {
1110                            size = bufsize;
1111                    }
1112                    else
1113                    {
1114                            in_uint8s(s, 2);        /* pad */
1115                            in_uint16_le(s, size);
1116                            in_uint8s(s, 4);        /* line_size, final_size */
1117                    }
1118                    in_uint8p(s, data, size);
1119                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1120                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1121                    {
1122                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1123                    }
1124                    else
1125                    {
1126                            DEBUG_RDP5(("Failed to decompress data\n"));
1127                    }
1128    
1129          return res;                  xfree(bmpdata);
1130            }
1131  }  }
1132    
1133  BOOL rdp_io_colcache_order(STREAM s, RDP_COLCACHE_ORDER *colours)  /* Process a palette update */
1134    void
1135    process_palette(STREAM s)
1136  {  {
1137          COLOURENTRY *entry;          COLOURENTRY *entry;
1138            COLOURMAP map;
1139            HCOLOURMAP hmap;
1140          int i;          int i;
1141    
1142          prs_io_uint8(s, &colours->cache_id);          in_uint8s(s, 2);        /* pad */
1143          lsb_io_uint16(s, &colours->map.ncolours);          in_uint16_le(s, map.ncolours);
1144            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;  
 }  
1145    
1146  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;  
1147    
1148          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;  
1149    
1150          for (i = 0; i < font->nglyphs; i++)          for (i = 0; i < map.ncolours; i++)
1151          {          {
1152                  glyph = &font->glyphs[i];                  entry = &map.colours[i];
1153                  res = res ? lsb_io_uint16(s, &glyph->character) : False;                  in_uint8(s, entry->red);
1154                  res = res ? lsb_io_uint16(s, &glyph->unknown  ) : False;                  in_uint8(s, entry->green);
1155                  res = res ? lsb_io_uint16(s, &glyph->baseline ) : False;                  in_uint8(s, entry->blue);
1156                  res = res ? lsb_io_uint16(s, &glyph->width    ) : False;          }
                 res = res ? lsb_io_uint16(s, &glyph->height   ) : False;  
1157    
1158                  datasize = (glyph->height * ((glyph->width + 7) / 8) + 3) & ~3;          hmap = ui_create_colourmap(&map);
1159                  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;  
                 }  
         }  
1160    
1161          return res;          xfree(map.colours);
1162  }  }
1163    
1164    /* Process an update PDU */
1165  /* CAPABILITIES */  static void
1166    process_update_pdu(STREAM s)
 /* Construct a general capability set */  
 void rdp_make_general_caps(RDP_GENERAL_CAPS *caps)  
1167  {  {
1168          caps->os_major_type = 1;          uint16 update_type, count;
         caps->os_minor_type = 3;  
         caps->ver_protocol = 0x200;  
 }  
1169    
1170  /* 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;  
1171    
1172          res = lsb_io_uint16(s, &pkt_length);          ui_begin_update();
1173          if (pkt_length != length)          switch (update_type)
1174          {          {
1175                  ERROR("Unrecognised capabilities size\n");                  case RDP_UPDATE_ORDERS:
1176                  return False;                          in_uint8s(s, 2);        /* pad */
1177          }                          in_uint16_le(s, count);
1178                            in_uint8s(s, 2);        /* pad */
1179                            process_orders(s, count);
1180                            break;
1181    
1182          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;                  case RDP_UPDATE_BITMAP:
1183          res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;                          process_bitmap_updates(s);
1184          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;  
1185    
1186          res = lsb_io_uint16(s, &pkt_length);                  case RDP_UPDATE_PALETTE:
1187          if (pkt_length != length)                          process_palette(s);
1188          {                          break;
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
1189    
1190          res = res ? lsb_io_uint16(s, &caps->preferred_bpp) : False;                  case RDP_UPDATE_SYNCHRONIZE:
1191          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;  
1192    
1193          res = lsb_io_uint16(s, &pkt_length);                  default:
1194          if (pkt_length != length)                          unimpl("update %d\n", update_type);
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
1195          }          }
1196            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;  
1197  }  }
1198    
1199  /* Parse single bitmap cache information structure */  /* Process a disconnect PDU */
1200  BOOL rdp_io_bmpcache_info(STREAM s, RDP_BMPCACHE_INFO *info)  void
1201    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1202  {  {
1203          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;  
1204    
1205          return True;          DEBUG(("Received disconnect PDU\n"));
1206  }  }
1207    
1208  /* Parse bitmap cache capability set */  /* Process data PDU */
1209  BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  static BOOL
1210    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1211  {  {
1212          uint16 length = RDP_CAPLEN_BMPCACHE;          uint8 data_pdu_type;
1213          uint16 pkt_length = length;          uint8 ctype;
1214          BOOL res;          uint16 clen;
1215          int i;          uint32 len;
   
         res = lsb_io_uint16(s, &pkt_length);  
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
         }  
1216    
1217          for (i = 0; i < 6; i++)          uint32 roff, rlen;
                 res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;  
1218    
1219          for (i = 0; i < 3; i++)          struct stream *ns = &(g_mppc_dict.ns);
                 res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
1220    
1221          return res;          in_uint8s(s, 6);        /* shareid, pad, streamid */
1222  }          in_uint16(s, len);
1223            in_uint8(s, data_pdu_type);
1224  /* Construct a control capability set */          in_uint8(s, ctype);
1225  void rdp_make_control_caps(RDP_CONTROL_CAPS *caps)          in_uint16(s, clen);
1226  {          clen -= 18;
         caps->control_interest = 2;  
         caps->detach_interest = 2;  
 }  
1227    
1228  /* 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)  
1229          {          {
1230                  ERROR("Unrecognised capabilities size\n");                  if (len > RDP_MPPC_DICT_SIZE)
1231                  return False;                          error("error decompressed packet size exceeds max\n");
1232          }                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1233                            error("error while decompressing packet\n");
1234    
1235          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;  
1236    
1237          return res;                  /* allocate memory and copy the uncompressed data into the temporary stream */
1238  }                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
1239    
1240  /* 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)  
 {  
 }  
1241    
1242  /* Parse activation capability set */                  ns->size = rlen;
1243  BOOL rdp_io_activate_caps(STREAM s, RDP_ACTIVATE_CAPS *caps)                  ns->end = (ns->data + ns->size);
1244  {                  ns->p = ns->data;
1245          uint16 length = RDP_CAPLEN_ACTIVATE;                  ns->rdp_hdr = ns->p;
         uint16 pkt_length = length;  
         BOOL res;  
1246    
1247          res = lsb_io_uint16(s, &pkt_length);                  s = ns;
         if (pkt_length != length)  
         {  
                 ERROR("Unrecognised capabilities size\n");  
                 return False;  
1248          }          }
1249    
1250          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)  
1251          {          {
1252                  ERROR("Unrecognised capabilities size\n");                  case RDP_DATA_PDU_UPDATE:
1253                  return False;                          process_update_pdu(s);
1254          }                          break;
1255    
1256          res = res ? lsb_io_uint16(s, &caps->colour_pointer) : False;                  case RDP_DATA_PDU_CONTROL:
1257          res = res ? lsb_io_uint16(s, &caps->cache_size    ) : False;                          DEBUG(("Received Control PDU\n"));
1258                            break;
1259    
1260          return res;                  case RDP_DATA_PDU_SYNCHRONISE:
1261  }                          DEBUG(("Received Sync PDU\n"));
1262                            break;
1263    
1264  /* Construct a share capability set */                  case RDP_DATA_PDU_POINTER:
1265  void rdp_make_share_caps(RDP_SHARE_CAPS *caps, uint16 userid)                          process_pointer_pdu(s);
1266  {                          break;
 }  
1267    
1268  /* Parse share capability set */                  case RDP_DATA_PDU_BELL:
1269  BOOL rdp_io_share_caps(STREAM s, RDP_SHARE_CAPS *caps)                          ui_bell();
1270  {                          break;
         uint16 length = RDP_CAPLEN_SHARE;  
         uint16 pkt_length = length;  
         BOOL res;  
1271    
1272          res = lsb_io_uint16(s, &pkt_length);                  case RDP_DATA_PDU_LOGON:
1273          if (pkt_length != length)                          DEBUG(("Received Logon PDU\n"));
1274          {                          /* User logged on */
1275                  ERROR("Unrecognised capabilities size\n");                          break;
                 return False;  
         }  
1276    
1277          res = res ? lsb_io_uint16(s, &caps->userid) : False;                  case RDP_DATA_PDU_DISCONNECT:
1278          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                          process_disconnect_pdu(s, ext_disc_reason);
1279                            return True;
1280    
1281          return res;                  default:
1282                            unimpl("data PDU %d\n", data_pdu_type);
1283            }
1284            return False;
1285  }  }
1286    
1287  /* Construct a colour cache capability set */  /* Process incoming packets */
1288  void rdp_make_colcache_caps(RDP_COLCACHE_CAPS *caps)  /* nevers gets out of here till app is done */
1289    void
1290    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1291  {  {
1292          caps->cache_size = 6;          while (rdp_loop(deactivated, ext_disc_reason))
1293                    ;
1294  }  }
1295    
1296  /* Parse colour cache capability set */  /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1297  BOOL rdp_io_colcache_caps(STREAM s, RDP_COLCACHE_CAPS *caps)  BOOL
1298    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1299  {  {
1300          uint16 length = RDP_CAPLEN_COLCACHE;          uint8 type;
1301          uint16 pkt_length = length;          BOOL disc = False;      /* True when a disconnect PDU was received */
1302          BOOL res;          BOOL cont = True;
1303            STREAM s;
1304    
1305          res = lsb_io_uint16(s, &pkt_length);          while (cont)
         if (pkt_length != length)  
1306          {          {
1307                  ERROR("Unrecognised capabilities size\n");                  s = rdp_recv(&type);
1308                  return False;                  if (s == NULL)
1309                            return False;
1310                    switch (type)
1311                    {
1312                            case RDP_PDU_DEMAND_ACTIVE:
1313                                    process_demand_active(s);
1314                                    *deactivated = False;
1315                                    break;
1316                            case RDP_PDU_DEACTIVATE:
1317                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1318                                    *deactivated = True;
1319                                    break;
1320                            case RDP_PDU_DATA:
1321                                    disc = process_data_pdu(s, ext_disc_reason);
1322                                    break;
1323                            case 0:
1324                                    break;
1325                            default:
1326                                    unimpl("PDU %d\n", type);
1327                    }
1328                    if (disc)
1329                            return False;
1330                    cont = g_next_packet < s->end;
1331          }          }
1332            return True;
         res = res ? lsb_io_uint16(s, &caps->cache_size) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad       ) : False;  
   
         return res;  
1333  }  }
1334    
1335  uint8 canned_caps[] = {  /* Establish a connection up to the RDP layer */
1336  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,  BOOL
1337  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,
1338  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)  
1339  {  {
1340          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");  
1341                  return False;                  return False;
         }  
1342    
1343          res = res ? prs_io_uint8s(s, canned_caps, RDP_CAPLEN_UNKNOWN-4) : False;          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1344            return True;
1345    }
1346    
1347          return res;  /* Disconnect from the RDP layer */
1348    void
1349    rdp_disconnect(void)
1350    {
1351            sec_disconnect();
1352  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26