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

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

  ViewVC Help
Powered by ViewVC 1.1.26