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

Legend:
Removed from v.7  
changed lines
  Added in v.828

  ViewVC Help
Powered by ViewVC 1.1.26