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

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

  ViewVC Help
Powered by ViewVC 1.1.26