/[rdesktop]/sourceforge.net/trunk/rdesktop/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26