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

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

  ViewVC Help
Powered by ViewVC 1.1.26