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

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

  ViewVC Help
Powered by ViewVC 1.1.26