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

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

  ViewVC Help
Powered by ViewVC 1.1.26