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

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

  ViewVC Help
Powered by ViewVC 1.1.26