/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.6  
changed lines
  Added in v.1364

  ViewVC Help
Powered by ViewVC 1.1.26