/[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

sourceforge.net/branches/RDESKTOP/rdesktop/rdp.c revision 3 by matty, Wed May 10 07:36:34 2000 UTC sourceforge.net/trunk/rdesktop/rdp.c 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    #include <unistd.h>
24    #include "rdesktop.h"
25    
26    #ifdef HAVE_ICONV
27    #ifdef HAVE_ICONV_H
28    #include <iconv.h>
29    #endif
30    
31    #ifndef ICONV_CONST
32    #define ICONV_CONST ""
33    #endif
34    #endif
35    
36    extern uint16 g_mcs_userid;
37    extern char g_username[64];
38    extern char g_codepage[16];
39    extern BOOL g_bitmap_compression;
40    extern BOOL g_orders;
41    extern BOOL g_encryption;
42    extern BOOL g_desktop_save;
43    extern BOOL g_polygon_ellipse_orders;
44    extern BOOL g_use_rdp5;
45    extern uint16 g_server_rdp_version;
46    extern uint32 g_rdp5_performanceflags;
47    extern int g_server_bpp;
48    extern int g_width;
49    extern int g_height;
50    extern BOOL g_bitmap_cache;
51    extern BOOL g_bitmap_cache_persist_enable;
52    
53    uint8 *g_next_packet;
54    uint32 g_rdp_shareid;
55    
56    extern RDPCOMP g_mppc_dict;
57    
58    #if WITH_DEBUG
59    static uint32 g_packetno;
60    #endif
61    
62    #ifdef HAVE_ICONV
63    static BOOL g_iconv_works = True;
64    #endif
65    
66    /* Receive an RDP packet */
67    static STREAM
68    rdp_recv(uint8 * type)
69    {
70            static STREAM rdp_s;
71            uint16 length, pdu_type;
72            uint8 rdpver;
73    
74            if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
75            {
76                    rdp_s = sec_recv(&rdpver);
77                    if (rdp_s == NULL)
78                            return NULL;
79                    if (rdpver == 0xff)
80                    {
81                            g_next_packet = rdp_s->end;
82                            *type = 0;
83                            return rdp_s;
84                    }
85                    else if (rdpver != 3)
86                    {
87                            /* rdp5_process should move g_next_packet ok */
88                            rdp5_process(rdp_s);
89                            *type = 0;
90                            return rdp_s;
91                    }
92    
93  /* Establish a connection up to the RDP layer */                  g_next_packet = rdp_s->p;
94  HCONN rdp_connect(char *server)          }
95            else
96            {
97                    rdp_s->p = g_next_packet;
98            }
99    
100            in_uint16_le(rdp_s, length);
101            /* 32k packets are really 8, keepalive fix */
102            if (length == 0x8000)
103            {
104                    g_next_packet += 8;
105                    *type = 0;
106                    return rdp_s;
107            }
108            in_uint16_le(rdp_s, pdu_type);
109            in_uint8s(rdp_s, 2);    /* userid */
110            *type = pdu_type & 0xf;
111    
112    #if WITH_DEBUG
113            DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
114            hexdump(g_next_packet, length);
115    #endif /*  */
116    
117            g_next_packet += length;
118            return rdp_s;
119    }
120    
121    /* Initialise an RDP data packet */
122    static STREAM
123    rdp_init_data(int maxlen)
124  {  {
125          HCONN conn;          STREAM s;
         RDP_ACTIVE_PDU active;  
         RDP_DATA_HEADER hdr;  
         RDP_UPDATE_PDU update;  
         RDP_ORDER_STATE os;  
         uint8 type;  
126    
127          memset(&os, 0, sizeof(os));          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
128            s_push_layer(s, rdp_hdr, 18);
129    
130          if ((conn = mcs_connect(server)) == NULL)          return s;
131                  return NULL;  }
132    
133          rdp_establish_key(conn);  /* Send an RDP data packet */
134          mcs_recv(conn, False); /* Server's licensing certificate */  static void
135          rdp_send_cert(conn);  rdp_send_data(STREAM s, uint8 data_pdu_type)
136          mcs_recv(conn, False);  {
137            uint16 length;
138          if (rdp_recv_pdu(conn, &type) && (type != RDP_PDU_DEMAND_ACTIVE))  
139          {          s_pop_layer(s, rdp_hdr);
140                  fprintf(stderr, "RDP error, expected Demand Active\n");          length = s->end - s->p;
141                  mcs_disconnect(conn);  
142                  return NULL;          out_uint16_le(s, length);
143          }          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
144            out_uint16_le(s, (g_mcs_userid + 1001));
145          rdp_io_active_pdu(&conn->in, &active, RDP_PDU_DEMAND_ACTIVE);  
146          rdp_send_confirm_active(conn);          out_uint32_le(s, g_rdp_shareid);
147          rdp_send_synchronize(conn);          out_uint8(s, 0);        /* pad */
148          rdp_send_control(conn, RDP_CTL_COOPERATE);          out_uint8(s, 1);        /* streamid */
149          rdp_send_control(conn, RDP_CTL_REQUEST_CONTROL);          out_uint16_le(s, (length - 14));
150          rdp_recv_pdu(conn, &type); // RDP_PDU_SYNCHRONIZE          out_uint8(s, data_pdu_type);
151          rdp_recv_pdu(conn, &type); // RDP_CTL_COOPERATE          out_uint8(s, 0);        /* compress_type */
152          rdp_recv_pdu(conn, &type); // RDP_CTL_GRANT_CONTROL          out_uint16(s, 0);       /* compress_len */
153          rdp_send_input(conn);  
154          rdp_send_fonts(conn, 1);          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
155          rdp_send_fonts(conn, 2);  }
156          rdp_recv_pdu(conn, &type); // RDP_PDU_UNKNOWN 0x28  
157          while (rdp_recv_pdu(conn, &type))  /* Output a string in Unicode */
158          {  void
159                  if (type != RDP_PDU_DATA)  rdp_out_unistr(STREAM s, char *string, int len)
160                          continue;  {
161    #ifdef HAVE_ICONV
162            size_t ibl = strlen(string), obl = len + 2;
163            static iconv_t iconv_h = (iconv_t) - 1;
164            char *pin = string, *pout = (char *)s->p;
165    
166                  rdp_io_data_header(&conn->in, &hdr);          memset(pout, 0, len + 4);
167    
168                  switch (hdr.data_pdu_type)          if (g_iconv_works)
169            {
170                    if (iconv_h == (iconv_t) - 1)
171                  {                  {
172                  case RDP_DATA_PDU_UPDATE:                          size_t i = 1, o = 4;
173                          rdp_io_update_pdu(&conn->in, &update);                          if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
174                          if (update.update_type == RDP_UPDATE_ORDERS)                          {
175                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
176                                            g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
177    
178                                    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                                  fprintf(stderr, "Received orders\n");                                  iconv_close(iconv_h);
186                                  process_orders(conn, &os);                                  iconv_h = (iconv_t) - 1;
187                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
188    
189                                    g_iconv_works = False;
190                                    rdp_out_unistr(s, string, len);
191                                    return;
192                          }                          }
193                          break;                          pin = string;
194                            pout = (char *) s->p;
195                  }                  }
         }  
196    
197          return conn;                  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  void prs_io_coord(STREAM s, uint16 *coord, BOOL delta)                          g_iconv_works = False;
204  {                          rdp_out_unistr(s, string, len);
205          uint8 change;                          return;
206                    }
207    
208                    s->p += len + 2;
209    
         if (delta)  
         {  
                 prs_io_uint8(s, &change);  
                 *coord += change;  
210          }          }
211          else          else
212    #endif
213          {          {
214                  lsb_io_uint16(s, coord);                  int i = 0, j = 0;
215    
216                    len += 2;
217    
218                    while (i < len)
219                    {
220                            s->p[i++] = string[j++];
221                            s->p[i++] = 0;
222                    }
223    
224                    s->p += len;
225          }          }
226  }  }
227    
228  void process_opaque_rect(HCONN conn, RDP_ORDER_STATE *os, BOOL delta)  /* 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          uint8 present;  #ifdef HAVE_ICONV
236          prs_io_uint8(&conn->in, &present);          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          if (present & 1)          if (g_iconv_works)
241                  prs_io_coord(&conn->in, &os->opaque_rect.x, delta);          {
242                    if (iconv_h == (iconv_t) - 1)
243                    {
244                            if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
245                            {
246                                    warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
247                                            WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
248    
249          if (present & 2)                                  g_iconv_works = False;
250                  prs_io_coord(&conn->in, &os->opaque_rect.y, delta);                                  return rdp_in_unistr(s, string, uni_len);
251                            }
252                    }
253    
254          if (present & 4)                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
255                  prs_io_coord(&conn->in, &os->opaque_rect.cx, delta);                  {
256                            iconv_close(iconv_h);
257                            iconv_h = (iconv_t) - 1;
258                            warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
259    
260          if (present & 8)                          g_iconv_works = False;
261                  prs_io_coord(&conn->in, &os->opaque_rect.cy, delta);                          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 (present & 16)                  while (i < uni_len / 2)
271                  prs_io_uint8(&conn->in, &os->opaque_rect.colour);                  {
272                            in_uint8a(s, &string[i++], 1);
273                            in_uint8s(s, 1);
274                    }
275    
276          fprintf(stderr, "Opaque rectangle at %d, %d\n", os->opaque_rect.x, os->opaque_rect.y);                  return i - 1;
277            }
278  }  }
279    
 void process_orders(HCONN conn, RDP_ORDER_STATE *os)  
 {  
         uint16 num_orders;  
         int processed = 0;  
         BOOL res = True;  
         //      unsigned char *p;  
   
         lsb_io_uint16(&conn->in, &num_orders);  
   
         conn->in.offset += 2;  
         //      p = &conn->in.data[conn->in.offset];  
   
         //      fprintf(stderr, "%02X %02X %02X %02X\n", p[0], p[1], p[2], p[3]);  
280    
281          while ((processed < num_orders) && res)  /* Parse a logon info packet */
282    static void
283    rdp_send_logon_info(uint32 flags, char *domain, char *user,
284                        char *password, char *program, char *directory)
285    {
286            char *ipaddr = tcp_get_address();
287            int len_domain = 2 * strlen(domain);
288            int len_user = 2 * strlen(user);
289            int len_password = 2 * strlen(password);
290            int len_program = 2 * strlen(program);
291            int len_directory = 2 * strlen(directory);
292            int len_ip = 2 * strlen(ipaddr);
293            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
294            int packetlen = 0;
295            uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
296            STREAM s;
297            time_t t = time(NULL);
298            time_t tzone;
299    
300    #if 0
301            /* enable rdp compression */
302            /* some problems still exist with rdp5 */
303            flags |= RDP_COMPRESSION;
304    #endif
305    
306            if (!g_use_rdp5 || 1 == g_server_rdp_version)
307            {
308                    DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
309    
310                    s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
311                                 + len_program + len_directory + 10);
312    
313                    out_uint32(s, 0);
314                    out_uint32_le(s, flags);
315                    out_uint16_le(s, len_domain);
316                    out_uint16_le(s, len_user);
317                    out_uint16_le(s, len_password);
318                    out_uint16_le(s, len_program);
319                    out_uint16_le(s, len_directory);
320                    rdp_out_unistr(s, domain, len_domain);
321                    rdp_out_unistr(s, user, len_user);
322                    rdp_out_unistr(s, password, len_password);
323                    rdp_out_unistr(s, program, len_program);
324                    rdp_out_unistr(s, directory, len_directory);
325            }
326            else
327          {          {
                 uint8 order_flags;  
328    
329                  prs_io_uint8(&conn->in, &order_flags);                  flags |= RDP_LOGON_BLOB;
330                    DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
331                    packetlen = 4 + /* Unknown uint32 */
332                            4 +     /* flags */
333                            2 +     /* len_domain */
334                            2 +     /* len_user */
335                            (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                  if (!(order_flags & RDP_ORDER_STANDARD))                  }
366                          return;                  if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
367                    {
368                            out_uint16_le(s, 0);
369                    }
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                  if (order_flags & RDP_ORDER_SECONDARY)                  }
390                    else
391                  {                  {
392                          RDP_SECONDARY_ORDER rso;                          out_uint16_le(s, 0);
393                    }
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                          rdp_io_secondary_order(&conn->in, &rso);                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
409                          switch (rso.type)                  out_uint32_le(s, tzone);
                         {  
                         case RDP_ORDER_BMPCACHE:  
                         {  
                                 RDP_BITMAP_HEADER rbh;  
                                 char output[8192];  
410    
411                                  rdp_io_bitmap_header(&conn->in, &rbh);                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
412                                  fprintf(stderr, "Decompressing bitmap %d x %d, final size %d\n", rbh.width, rbh.height, rbh.final_size);                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
                                 bitmap_decompress(conn->in.data  
                                                   + conn->in.offset, rbh.size,  
                                                   output, rbh.width);  
                                 conn->in.offset += rbh.size;  
                                 break;  
                         }  
                         default:  
                                 fprintf(stderr, "Unknown secondary order %d\n",  
                                         rso.type);  
                                 return;  
                         }  
413    
414                    out_uint32_le(s, 0x0a0000);
415                    out_uint32_le(s, 0x050000);
416                    out_uint32_le(s, 3);
417                    out_uint32_le(s, 0);
418                    out_uint32_le(s, 0);
419    
420                  }                  rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
421                    out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
422    
423                  if (order_flags & RDP_ORDER_CHANGE)                  out_uint32_le(s, 0x30000);
424                          prs_io_uint8(&conn->in, &os->order_type);                  out_uint32_le(s, 0x050000);
425                    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    
                 switch (os->order_type)  
                 {  
                 case RDP_ORDER_OPAQUE_RECT:  
                         process_opaque_rect(conn, os, order_flags & RDP_ORDER_DELTA);  
                         break;  
                 default:  
                         fprintf(stderr, "Unknown order %d\n", os->order_type);  
                         return;  
                 }  
432    
                 processed++;  
433          }          }
434            s_mark_end(s);
435            sec_send(s, sec_flags);
436  }  }
437    
438  /* Work this out later. This is useless anyway when encryption is off. */  /* Send a control PDU */
439  uint8 precanned_key_packet[] = {  static void
440     0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00,  rdp_send_control(uint16 action)
    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  
 };  
   
 /* Create an RC4 key and transfer it to the server */  
 void rdp_establish_key(HCONN conn)  
441  {  {
442          mcs_init_data(conn);          STREAM s;
         memcpy(conn->out.data + conn->out.offset, precanned_key_packet,  
                sizeof(precanned_key_packet));  
         conn->out.offset += sizeof(precanned_key_packet);  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
   
 /* Horrible horrible certificate stuff. Work out later. */  
 uint8 precanned_cert_packet[] = {  
 0x80,0x00,0x00,0x00,0x12,0x02,0xb4,0x04,0x01,0x00,0x00,  
 0x00,0x00,0x00,0x01,0x02,0x9d,0xa3,0x7a,0x93,0x34,0x7b,0x28,0x37,0x24,0xa0,0x1f,  
 0x61,0x26,0xfd,0x96,0x3a,0x92,0x83,0xf3,0xe9,0x6a,0x2e,0x81,0x7c,0x2c,0xe4,0x72,//  
 0x01,0x18,0xe9,0xa1,0x0f,0x00,0x00,0x48,0x00,0x84,0x23,0x90,0xe6,0xd3,0xf8,0x20,  
 0xdb,0xa8,0x1b,0xb2,0xd0,0x78,0x2c,0x35,0xde,0xe3,0x0e,0x63,0x40,0xca,0xac,0x71,  
 0xc9,0x17,0x49,0x05,0x25,0xeb,0x9b,0xd0,0xa6,0x5c,0x90,0x3e,0x9d,0x4b,0x27,0x01,  
 0x79,0x1c,0x22,0xfb,0x3c,0x2c,0xb9,0x9f,0xf5,0x21,0xf3,0xee,0xd5,0x4d,0x47,0x1c,  
 0x85,0xbe,0x83,0x93,0xe8,0xed,0x8c,0x5c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  
 0x00,0x01,0x00,0x10,0x04,0x30,0x82,0x04,0x0c,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,  
 0x0d,0x01,0x07,0x02,0xa0,0x82,0x03,0xfd,0x30,0x82,0x03,0xf9,0x02,0x01,0x01,0x31,  
 0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x82,  
 0x03,0xe1,0x30,0x82,0x01,0x77,0x30,0x82,0x01,0x25,0xa0,0x03,0x02,0x01,0x02,0x02,  
 0x08,0x01,0xbf,0x06,0x84,0x9d,0xdb,0x2d,0xe0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,  
 0x86,0xf7,0x0d,0x01,0x01,0x01,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,0x31,0x32,0x30,0x32,  
 0x30,0x34,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x31,0x32,0x30,0x32,0x30,  
 0x34,0x5a,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,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,0x13,0x30,0x11,0x30,0x0f,  
 0x06,0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x00,0x30,  
 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x41,0x00,0x14,0x04,0x67,  
 0x28,0xc8,0xd3,0x1f,0x13,0x14,0x2e,0x2c,0x93,0x09,0x25,0xbb,0xbe,0x86,0x6a,0xd3,  
 0x47,0x6f,0x44,0x16,0x7b,0x94,0x8c,0xb2,0xa2,0xd5,0xf7,0x4f,0xb1,0x8f,0x7f,0xde,  
 0x0b,0x88,0x34,0x4a,0x1d,0xdc,0xa1,0xfd,0x26,0xbd,0x43,0xbb,0x38,0xf1,0x87,0x34,  
 0xbb,0xe9,0x3b,0xfa,0x7f,0x1e,0xff,0xe1,0x10,0x7e,0xee,0x6e,0xd8,0x30,0x82,0x02,  
 0x62,0x30,0x82,0x02,0x10,0xa0,0x03,0x02,0x01,0x02,0x02,0x05,0x01,0x00,0x00,0x00,  
 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x38,0x31,0x36,  
 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x1e,0x0a,0x00,0x4e,0x00,0x54,0x00,0x54,0x00,  
 0x53,0x00,0x45,0x30,0x21,0x06,0x03,0x55,0x04,0x07,0x1e,0x1a,0x00,0x4d,0x00,0x69,  
 0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x2e,  
 0x00,0x63,0x00,0x6f,0x00,0x6d,0x30,0x1e,0x17,0x0d,0x39,0x39,0x30,0x39,0x32,0x34,  
 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x34,0x39,0x30,0x39,0x32,0x34,0x30,  
 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x79,0x31,0x77,0x30,0x17,0x06,0x03,0x55,0x04,  
 0x03,0x1e,0x10,0x00,0x52,0x00,0x45,0x00,0x53,0x00,0x37,0x00,0x2d,0x00,0x4e,0x00,  
 0x45,0x00,0x57,0x30,0x17,0x06,0x03,0x55,0x04,0x07,0x1e,0x10,0x00,0x7a,0x00,0x32,  
 0x00,0x32,0x00,0x33,0x00,0x32,0x00,0x32,0x00,0x30,0x00,0x33,0x30,0x43,0x06,0x03,  
 0x55,0x04,0x05,0x1e,0x3c,0x00,0x31,0x00,0x42,0x00,0x63,0x00,0x4b,0x00,0x65,0x00,  
 0x57,0x00,0x50,0x00,0x6c,0x00,0x37,0x00,0x58,0x00,0x47,0x00,0x61,0x00,0x73,0x00,  
 0x38,0x00,0x4a,0x00,0x79,0x00,0x50,0x00,0x34,0x00,0x30,0x00,0x7a,0x00,0x49,0x00,  
 0x6d,0x00,0x6e,0x00,0x6f,0x00,0x51,0x00,0x5a,0x00,0x59,0x00,0x3d,0x00,0x0d,0x00,  
 0x0a,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,  
 0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0x91,0xb2,0x16,0x1c,0xae,0x4f,  
 0x7f,0x7c,0xaf,0x57,0x2b,0x23,0x4c,0x0c,0x25,0x3c,0x4f,0x66,0x9d,0x25,0xc3,0x4f,  
 0x29,0xee,0x8b,0xda,0x4e,0x95,0xe7,0x3b,0xaa,0xc0,0xa7,0xba,0xaf,0x99,0x8c,0x47,  
 0x24,0x8b,0x09,0x77,0xbc,0x2c,0xf4,0xe7,0x1a,0x07,0x58,0x7b,0x11,0x37,0x2a,0xa8,  
 0x90,0xc3,0x50,0x92,0x80,0x15,0xc5,0xda,0x51,0x8b,0x02,0x03,0x01,0x00,0x01,0xa3,  
 0x81,0xc3,0x30,0x81,0xc0,0x30,0x14,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,  
 0x12,0x04,0x01,0x01,0xff,0x04,0x04,0x01,0x00,0x01,0x00,0x30,0x3c,0x06,0x09,0x2b,  
 0x06,0x01,0x04,0x01,0x82,0x37,0x12,0x02,0x01,0x01,0xff,0x04,0x2c,0x4d,0x00,0x69,  
 0x00,0x63,0x00,0x72,0x00,0x6f,0x00,0x73,0x00,0x6f,0x00,0x66,0x00,0x74,0x00,0x20,  
 0x00,0x43,0x00,0x6f,0x00,0x72,0x00,0x70,0x00,0x6f,0x00,0x72,0x00,0x61,0x00,0x74,  
 0x00,0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0x30,0x4c,0x06,0x09,0x2b,0x06,0x01,  
 0x04,0x01,0x82,0x37,0x12,0x05,0x01,0x01,0xff,0x04,0x3c,0x00,0x10,0x00,0x00,0x01,  
 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x18,0x00,0x18,0x00,0x30,  
 0x00,0x01,0x00,0x32,0x00,0x33,0x00,0x36,0x00,0x2d,0x00,0x34,0x00,0x2e,0x00,0x30,  
 0x00,0x30,0x00,0x2d,0x00,0x45,0x00,0x58,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,  
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x1c,0x06,0x03,0x55,0x1d,0x23,0x01,0x01,  
 0xff,0x04,0x12,0x30,0x10,0xa1,0x07,0x81,0x05,0x4e,0x54,0x54,0x53,0x45,0x82,0x05,  
 0x01,0x00,0x00,0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,  
 0x03,0x41,0x00,0x7b,0x1d,0xfd,0x24,0xea,0xf2,0xe8,0x17,0xdd,0x88,0x7e,0xfd,0xee,  
 0x28,0x61,0x7a,0x02,0xc3,0x73,0xcf,0x32,0x0f,0x7c,0x66,0x87,0x31,0xa7,0xbe,0x1b,  
 0x31,0xe2,0x20,0xa5,0x76,0x91,0x68,0x97,0x53,0x9e,0x80,0xcd,0x2b,0xd0,0x8e,0x8b,  
 0x7f,0x89,0x1b,0x62,0xa8,0xf8,0xee,0x5e,0x56,0xbd,0x9c,0x6b,0x80,0x06,0x54,0xd3,  
 0xf0,0xbf,0xb2,0x31,0x00,0x01,0x00,0x14,0x00,0xc7,0x32,0xf2,0x5b,0x98,0x0e,0x04,  
 0x49,0xa0,0x27,0x7e,0xf5,0xf6,0x0f,0xda,0x08,0x1d,0xe9,0x79,0xd1,0x31,0xc6,0x50,  
 0x90,0x4a,0xd3,0x1f,0x1d,0xf0,0x65,0x0d,0xb6,0x1f,0xaf,0xc9,0x1d  
 };  
443    
444  /* Send license certificate and related data to the server */          s = rdp_init_data(8);
 void rdp_send_cert(HCONN conn)  
 {  
         mcs_init_data(conn);  
         prs_io_uint8s(&conn->out, precanned_cert_packet, sizeof(precanned_cert_packet));  
         MARK_END(conn->out);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
445    
446  /* Initialise RDP transport packet */          out_uint16_le(s, action);
447  void rdp_init(HCONN conn)          out_uint16(s, 0);       /* userid */
448  {          out_uint32(s, 0);       /* control id */
449          mcs_init_data(conn);  
450          PUSH_LAYER(conn->out, rdp_offset, 6);          s_mark_end(s);
451            rdp_send_data(s, RDP_DATA_PDU_CONTROL);
452  }  }
453    
454  /* Transmit RDP transport packet */  /* Send a synchronisation PDU */
455  void rdp_send(HCONN conn, uint16 pdu_type)  static void
456    rdp_send_synchronise(void)
457  {  {
458          RDP_HEADER hdr;          STREAM s;
         int length;  
459    
460          POP_LAYER(conn->out, rdp_offset);          s = rdp_init_data(4);
         length = conn->out.end - conn->out.offset;  
         rdp_make_header(&hdr, length, pdu_type, conn->mcs_userid);  
         rdp_io_header(&conn->out, &hdr);  
         mcs_send_data(conn, MCS_GLOBAL_CHANNEL, True);  
 }  
461    
462  /* Initialise RDP transport data packet */          out_uint16_le(s, 1);    /* type */
463  void rdp_init_data(HCONN conn)          out_uint16_le(s, 1002);
464  {  
465          mcs_init_data(conn);          s_mark_end(s);
466          PUSH_LAYER(conn->out, rdp_offset, 18);          rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
467  }  }
468    
469  /* Transmit RDP transport data packet */  /* Send a single input event */
470  void rdp_send_data(HCONN conn, uint16 data_pdu_type)  void
471    rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
472  {  {
473          RDP_HEADER hdr;          STREAM s;
         RDP_DATA_HEADER datahdr;  
         int length = conn->out.end - conn->out.offset;  
474    
475          POP_LAYER(conn->out, rdp_offset);          s = rdp_init_data(16);
         length = conn->out.end - conn->out.offset;  
         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);  
 }  
476    
477  void rdp_send_confirm_active(HCONN conn)          out_uint16_le(s, 1);    /* number of events */
478  {          out_uint16(s, 0);       /* pad */
479          RDP_ACTIVE_PDU active;  
480            out_uint32_le(s, time);
481            out_uint16_le(s, message_type);
482            out_uint16_le(s, device_flags);
483            out_uint16_le(s, param1);
484            out_uint16_le(s, param2);
485    
486          rdp_init(conn);          s_mark_end(s);
487          rdp_make_active_pdu(&active, 0x103ea, conn->mcs_userid);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
         rdp_io_active_pdu(&conn->out, &active, RDP_PDU_CONFIRM_ACTIVE);  
         MARK_END(conn->out);  
         rdp_send(conn, RDP_PDU_CONFIRM_ACTIVE);  
488  }  }
489    
490  void rdp_send_synchronize(HCONN conn)  /* Inform the server on the contents of the persistent bitmap cache */
491    static void
492    rdp_enum_bmpcache2(void)
493  {  {
494          RDP_SYNCHRONIZE_PDU sync;          STREAM s;
495            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
496            uint32 num_keys, offset, count, flags;
497    
498          rdp_init_data(conn);          offset = 0;
499          rdp_make_synchronize_pdu(&sync, 1002);          num_keys = pstcache_enumerate(2, keylist);
         rdp_io_synchronize_pdu(&conn->out, &sync);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_SYNCHRONIZE);  
 }  
500    
501  void rdp_send_control(HCONN conn, uint16 action)          while (offset < num_keys)
502  {          {
503          RDP_CONTROL_PDU control;                  count = MIN(num_keys - offset, 169);
504    
505          rdp_init_data(conn);                  s = rdp_init_data(24 + count * sizeof(HASH_KEY));
         rdp_make_control_pdu(&control, action);  
         rdp_io_control_pdu(&conn->out, &control);  
         MARK_END(conn->out);  
         rdp_send_data(conn, RDP_DATA_PDU_CONTROL);  
 }  
506    
507  void rdp_send_fonts(HCONN conn, uint16 seqno)                  flags = 0;
508  {                  if (offset == 0)
509          RDP_FONT_PDU fonts;                          flags |= PDU_FLAG_FIRST;
510                    if (num_keys - offset <= 169)
511                            flags |= PDU_FLAG_LAST;
512    
513          rdp_init_data(conn);                  /* header */
514          rdp_make_font_pdu(&fonts, seqno);                  out_uint32_le(s, 0);
515          rdp_io_font_pdu(&conn->out, &fonts);                  out_uint16_le(s, count);
516          MARK_END(conn->out);                  out_uint16_le(s, 0);
517          rdp_send_data(conn, RDP_DATA_PDU_FONT2);                  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  void rdp_send_input(HCONN conn)                  /* list */
525  {                  out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
         RDP_INPUT_PDU input;  
526    
527          rdp_init_data(conn);                  s_mark_end(s);
528          rdp_make_input_pdu(&input);                  rdp_send_data(s, 0x2b);
529          rdp_io_input_pdu(&conn->out, &input);  
530          MARK_END(conn->out);                  offset += 169;
531          rdp_send_data(conn, RDP_DATA_PDU_INPUT);          }
532  }  }
533    
534  BOOL rdp_recv_pdu(HCONN conn, uint8 *type)  /* Send an (empty) font information PDU */
535    static void
536    rdp_send_fonts(uint16 seq)
537  {  {
538          RDP_HEADER hdr;          STREAM s;
539    
540          if (!mcs_recv(conn, False) || !rdp_io_header(&conn->in, &hdr))          s = rdp_init_data(8);
                 return False;  
541    
542          *type = hdr.pdu_type & 0xf;          out_uint16(s, 0);       /* number of fonts */
543          return True;          out_uint16_le(s, 0);    /* pad? */
544  }          out_uint16_le(s, seq);  /* unknown */
545            out_uint16_le(s, 0x32); /* entry size */
546    
547  /* Disconnect from the RDP layer */          s_mark_end(s);
548  void rdp_disconnect(HCONN conn)          rdp_send_data(s, RDP_DATA_PDU_FONT2);
 {  
         mcs_disconnect(conn);  
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);
848          {  
849                  fprintf(stderr, "Unrecognised capabilities size\n");          in_uint16_le(s, width);
850                  return False;          in_uint16_le(s, height);
         }  
851    
852          res = res ? lsb_io_uint16(s, &caps->os_major_type ) : False;          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
         res = res ? lsb_io_uint16(s, &caps->os_minor_type ) : False;  
         res = res ? lsb_io_uint16(s, &caps->ver_protocol  ) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad1          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_types) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad2          ) : False;  
         res = res ? lsb_io_uint16(s, &caps->cap_update    ) : False;  
         res = res ? lsb_io_uint16(s, &caps->remote_unshare) : False;  
         res = res ? lsb_io_uint16(s, &caps->compress_level) : False;  
         res = res ? lsb_io_uint16(s, &caps->pad3          ) : False;  
   
         return res;  
 }  
   
 BOOL rdp_io_bitmap_caps(STREAM s, RDP_BITMAP_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BITMAP;  
         uint16 pkt_length = length;  
         BOOL res;  
853    
854          res = lsb_io_uint16(s, &pkt_length);          /*
855          if (pkt_length != length)           * 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 */
   
 BOOL rdp_io_bmpcache_caps(STREAM s, RDP_BMPCACHE_CAPS *caps)  
 {  
         uint16 length = RDP_CAPLEN_BMPCACHE;  
         uint16 pkt_length = length;  
         BOOL res;  
         int i;  
885    
886          res = lsb_io_uint16(s, &pkt_length);          for (n = 0; n < ncapsets; n++)
         if (pkt_length != length)  
887          {          {
888                  fprintf(stderr, "Unrecognised capabilities size\n");                  if (s->p > start + length)
889                  return False;                          return;
         }  
890    
891          for (i = 0; i < 6; i++)                  in_uint16_le(s, capset_type);
892                  res = res ? lsb_io_uint32(s, &caps->unused[i]) : False;                  in_uint16_le(s, capset_length);
893    
894          for (i = 0; i < 3; i++)                  next = s->p + capset_length - 4;
895                  res = res ? rdp_io_bmpcache_info(s, &caps->caches[i]) : False;  
896                    switch (capset_type)
897                    {
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;
         BOOL res;  
917    
918          res = lsb_io_uint16(s, &pkt_length);          in_uint32_le(s, g_rdp_shareid);
919          if (pkt_length != length)          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            if (g_use_rdp5)
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;
         BOOL res;  
1006    
1007          res = lsb_io_uint16(s, &pkt_length);          in_uint16_le(s, message_type);
1008          if (pkt_length != length)          in_uint8s(s, 2);        /* pad */
1009    
1010            switch (message_type)
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                    case RDP_POINTER_COLOR:
1020                            process_colour_pointer_pdu(s);
1021                            break;
1022    
1023          res = res ? lsb_io_uint16(s, &caps->userid) : False;                  case RDP_POINTER_CACHED:
1024          res = res ? lsb_io_uint16(s, &caps->pad   ) : False;                          process_cached_pointer_pdu(s);
1025                            break;
1026    
1027          return res;                  case RDP_POINTER_SYSTEM:
1028                            process_system_pointer_pdu(s);
1029                            break;
1030    
1031                    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.3  
changed lines
  Added in v.866

  ViewVC Help
Powered by ViewVC 1.1.26