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

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

  ViewVC Help
Powered by ViewVC 1.1.26