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

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

  ViewVC Help
Powered by ViewVC 1.1.26