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

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

  ViewVC Help
Powered by ViewVC 1.1.26