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

Legend:
Removed from v.10  
changed lines
  Added in v.738

  ViewVC Help
Powered by ViewVC 1.1.26