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

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

  ViewVC Help
Powered by ViewVC 1.1.26