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

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

  ViewVC Help
Powered by ViewVC 1.1.26