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

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

  ViewVC Help
Powered by ViewVC 1.1.26