/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdp.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26