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

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

  ViewVC Help
Powered by ViewVC 1.1.26