/[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 24 by matty, Sat Jan 6 03:12:10 2001 UTC revision 1238 by matthewc, Wed Jun 14 08:59:03 2006 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;  
   
 /* Initialise an RDP packet */  
 static STREAM rdp_init(int maxlen)  
 {  
         STREAM s;  
   
         s = sec_init(SEC_ENCRYPT, maxlen + 6);  
         s_push_layer(s, rdp_hdr, 6);  
   
         return s;  
 }  
30    
31  /* Send an RDP packet */  #ifndef ICONV_CONST
32  static void rdp_send(STREAM s, uint8 pdu_type)  #define ICONV_CONST ""
33  {  #endif
34          uint16 length;  #endif
35    
36          s_pop_layer(s, rdp_hdr);  extern uint16 g_mcs_userid;
37          length = s->end - s->p;  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_depth;
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    extern BOOL g_numlock_sync;
53    
54    uint8 *g_next_packet;
55    uint32 g_rdp_shareid;
56    
57    extern RDPCOMP g_mppc_dict;
58    
59    /* Session Directory support */
60    extern BOOL g_redirect;
61    extern char g_redirect_server[64];
62    extern char g_redirect_domain[16];
63    extern char g_redirect_password[64];
64    extern char g_redirect_username[64];
65    extern char g_redirect_cookie[128];
66    extern uint32 g_redirect_flags;
67    /* END Session Directory support */
68    
69          out_uint16_le(s, length);  #if WITH_DEBUG
70          out_uint16_le(s, (pdu_type | 0x10));    /* Version 1 */  static uint32 g_packetno;
71          out_uint16_le(s, (mcs_userid + 1001));  #endif
72    
73          sec_send(s, SEC_ENCRYPT);  #ifdef HAVE_ICONV
74  }  static BOOL g_iconv_works = True;
75    #endif
76    
77  /* Receive an RDP packet */  /* Receive an RDP packet */
78  static STREAM rdp_recv(uint8 *type)  static STREAM
79    rdp_recv(uint8 * type)
80  {  {
81          static STREAM rdp_s;          static STREAM rdp_s;
82          uint16 length, pdu_type;          uint16 length, pdu_type;
83            uint8 rdpver;
84    
85          if ((rdp_s == NULL) || (next_packet >= rdp_s->end))          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
86          {          {
87                  rdp_s = sec_recv();                  rdp_s = sec_recv(&rdpver);
88                  if (rdp_s == NULL)                  if (rdp_s == NULL)
89                          return NULL;                          return NULL;
90                    if (rdpver == 0xff)
91                    {
92                            g_next_packet = rdp_s->end;
93                            *type = 0;
94                            return rdp_s;
95                    }
96                    else if (rdpver != 3)
97                    {
98                            /* rdp5_process should move g_next_packet ok */
99                            rdp5_process(rdp_s);
100                            *type = 0;
101                            return rdp_s;
102                    }
103    
104                  next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
105          }          }
106          else          else
107          {          {
108                  rdp_s->p = next_packet;                  rdp_s->p = g_next_packet;
109          }          }
110    
111          in_uint16_le(rdp_s, length);          in_uint16_le(rdp_s, length);
112            /* 32k packets are really 8, keepalive fix */
113            if (length == 0x8000)
114            {
115                    g_next_packet += 8;
116                    *type = 0;
117                    return rdp_s;
118            }
119          in_uint16_le(rdp_s, pdu_type);          in_uint16_le(rdp_s, pdu_type);
120          in_uint8s(rdp_s, 2);    /* userid */          in_uint8s(rdp_s, 2);    /* userid */
   
         next_packet += length;  
121          *type = pdu_type & 0xf;          *type = pdu_type & 0xf;
122    
123  #if RDP_DEBUG  #if WITH_DEBUG
124          DEBUG("RDP packet (type %x):\n", *type);          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
125          hexdump(rdp_s->p, length);          hexdump(g_next_packet, length);
126  #endif  #endif /*  */
127    
128            g_next_packet += length;
129          return rdp_s;          return rdp_s;
130  }  }
131    
132  /* Initialise an RDP data packet */  /* Initialise an RDP data packet */
133  static STREAM rdp_init_data(int maxlen)  static STREAM
134    rdp_init_data(int maxlen)
135  {  {
136          STREAM s;          STREAM s;
137    
138          s = sec_init(SEC_ENCRYPT, maxlen + 18);          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
139          s_push_layer(s, rdp_hdr, 18);          s_push_layer(s, rdp_hdr, 18);
140    
141          return s;          return s;
142  }  }
143    
144  /* Send an RDP data packet */  /* Send an RDP data packet */
145  static void rdp_send_data(STREAM s, uint8 data_pdu_type)  static void
146    rdp_send_data(STREAM s, uint8 data_pdu_type)
147  {  {
148          uint16 length;          uint16 length;
149    
# Line 108  static void rdp_send_data(STREAM s, uint Line 152  static void rdp_send_data(STREAM s, uint
152    
153          out_uint16_le(s, length);          out_uint16_le(s, length);
154          out_uint16_le(s, (RDP_PDU_DATA | 0x10));          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
155          out_uint16_le(s, (mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
156    
157          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
158          out_uint8(s, 0);        /* pad */          out_uint8(s, 0);        /* pad */
159          out_uint8(s, 1);        /* streamid */          out_uint8(s, 1);        /* streamid */
160          out_uint16(s, (length - 14));          out_uint16_le(s, (length - 14));
161          out_uint8(s, data_pdu_type);          out_uint8(s, data_pdu_type);
162          out_uint8(s, 0);        /* compress_type */          out_uint8(s, 0);        /* compress_type */
163          out_uint16(s, 0);       /* compress_len */          out_uint16(s, 0);       /* compress_len */
164    
165          sec_send(s, SEC_ENCRYPT);          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
166  }  }
167    
168  /* Output a string in Unicode */  /* Output a string in Unicode */
169  void rdp_out_unistr(STREAM s, char *string, int len)  void
170    rdp_out_unistr(STREAM s, char *string, int len)
171  {  {
172          int i = 0, j = 0;  #ifdef HAVE_ICONV
173            size_t ibl = strlen(string), obl = len + 2;
174            static iconv_t iconv_h = (iconv_t) - 1;
175            char *pin = string, *pout = (char *) s->p;
176    
177          len += 2;          memset(pout, 0, len + 4);
178    
179          while (i < len)          if (g_iconv_works)
180          {          {
181                  s->p[i++] = string[j++];                  if (iconv_h == (iconv_t) - 1)
182                  s->p[i++] = 0;                  {
183                            size_t i = 1, o = 4;
184                            if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
185                            {
186                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
187                                            g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
188    
189                                    g_iconv_works = False;
190                                    rdp_out_unistr(s, string, len);
191                                    return;
192                            }
193                            if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
194                                (size_t) - 1)
195                            {
196                                    iconv_close(iconv_h);
197                                    iconv_h = (iconv_t) - 1;
198                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
199    
200                                    g_iconv_works = False;
201                                    rdp_out_unistr(s, string, len);
202                                    return;
203                            }
204                            pin = string;
205                            pout = (char *) s->p;
206                    }
207    
208                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
209                    {
210                            iconv_close(iconv_h);
211                            iconv_h = (iconv_t) - 1;
212                            warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
213    
214                            g_iconv_works = False;
215                            rdp_out_unistr(s, string, len);
216                            return;
217                    }
218    
219                    s->p += len + 2;
220    
221            }
222            else
223    #endif
224            {
225                    int i = 0, j = 0;
226    
227                    len += 2;
228    
229                    while (i < len)
230                    {
231                            s->p[i++] = string[j++];
232                            s->p[i++] = 0;
233                    }
234    
235                    s->p += len;
236            }
237    }
238    
239    /* Input a string in Unicode
240     *
241     * Returns str_len of string
242     */
243    int
244    rdp_in_unistr(STREAM s, char *string, int uni_len)
245    {
246    #ifdef HAVE_ICONV
247            size_t ibl = uni_len, obl = uni_len;
248            char *pin = (char *) s->p, *pout = string;
249            static iconv_t iconv_h = (iconv_t) - 1;
250    
251            if (g_iconv_works)
252            {
253                    if (iconv_h == (iconv_t) - 1)
254                    {
255                            if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
256                            {
257                                    warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
258                                            WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
259    
260                                    g_iconv_works = False;
261                                    return rdp_in_unistr(s, string, uni_len);
262                            }
263                    }
264    
265                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
266                    {
267                            iconv_close(iconv_h);
268                            iconv_h = (iconv_t) - 1;
269                            warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
270    
271                            g_iconv_works = False;
272                            return rdp_in_unistr(s, string, uni_len);
273                    }
274    
275                    /* we must update the location of the current STREAM for future reads of s->p */
276                    s->p += uni_len;
277    
278                    return pout - string;
279          }          }
280            else
281    #endif
282            {
283                    int i = 0;
284    
285                    while (i < uni_len / 2)
286                    {
287                            in_uint8a(s, &string[i++], 1);
288                            in_uint8s(s, 1);
289                    }
290    
291          s->p += len;                  return i - 1;
292            }
293  }  }
294    
295    
296  /* Parse a logon info packet */  /* Parse a logon info packet */
297  static void rdp_send_logon_info(uint32 flags, char *domain, char *user,  static void
298                                  char *password, char *program,  rdp_send_logon_info(uint32 flags, char *domain, char *user,
299                                  char *directory)                      char *password, char *program, char *directory)
300  {  {
301            char *ipaddr = tcp_get_address();
302          int len_domain = 2 * strlen(domain);          int len_domain = 2 * strlen(domain);
303          int len_user = 2 * strlen(user);          int len_user = 2 * strlen(user);
304          int len_password = 2 * strlen(password);          int len_password = 2 * strlen(password);
305          int len_program = 2 * strlen(program);          int len_program = 2 * strlen(program);
306          int len_directory = 2 * strlen(directory);          int len_directory = 2 * strlen(directory);
307          uint32 sec_flags = SEC_LOGON_INFO | SEC_ENCRYPT;          int len_ip = 2 * strlen(ipaddr);
308            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
309            int packetlen = 0;
310            uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
311          STREAM s;          STREAM s;
312            time_t t = time(NULL);
313            time_t tzone;
314    
315          s = sec_init(sec_flags, 18 + len_domain + len_user + len_password          if (!g_use_rdp5 || 1 == g_server_rdp_version)
316                       + len_program + len_directory + 10);          {
317                    DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
318    
319                    s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
320                                 + len_program + len_directory + 10);
321    
322                    out_uint32(s, 0);
323                    out_uint32_le(s, flags);
324                    out_uint16_le(s, len_domain);
325                    out_uint16_le(s, len_user);
326                    out_uint16_le(s, len_password);
327                    out_uint16_le(s, len_program);
328                    out_uint16_le(s, len_directory);
329                    rdp_out_unistr(s, domain, len_domain);
330                    rdp_out_unistr(s, user, len_user);
331                    rdp_out_unistr(s, password, len_password);
332                    rdp_out_unistr(s, program, len_program);
333                    rdp_out_unistr(s, directory, len_directory);
334            }
335            else
336            {
337    
338                    flags |= RDP_LOGON_BLOB;
339                    DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
340                    packetlen = 4 + /* Unknown uint32 */
341                            4 +     /* flags */
342                            2 +     /* len_domain */
343                            2 +     /* len_user */
344                            (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
345                            (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
346                            2 +     /* len_program */
347                            2 +     /* len_directory */
348                            (0 < len_domain ? len_domain : 2) +     /* domain */
349                            len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
350                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
351                            (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
352                            2 +     /* Client ip length */
353                            len_ip +        /* Client ip */
354                            2 +     /* DLL string length */
355                            len_dll +       /* DLL string */
356                            2 +     /* Unknown */
357                            2 +     /* Unknown */
358                            64 +    /* Time zone #0 */
359                            2 +     /* Unknown */
360                            64 +    /* Time zone #1 */
361                            32;     /* Unknown */
362    
363                    s = sec_init(sec_flags, packetlen);
364                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
365    
366                    out_uint32(s, 0);       /* Unknown */
367                    out_uint32_le(s, flags);
368                    out_uint16_le(s, len_domain);
369                    out_uint16_le(s, len_user);
370                    if (flags & RDP_LOGON_AUTO)
371                    {
372                            out_uint16_le(s, len_password);
373    
374                    }
375                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
376                    {
377                            out_uint16_le(s, 0);
378                    }
379                    out_uint16_le(s, len_program);
380                    out_uint16_le(s, len_directory);
381                    if (0 < len_domain)
382                            rdp_out_unistr(s, domain, len_domain);
383                    else
384                            out_uint16_le(s, 0);
385                    rdp_out_unistr(s, user, len_user);
386                    if (flags & RDP_LOGON_AUTO)
387                    {
388                            rdp_out_unistr(s, password, len_password);
389                    }
390                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
391                    {
392                            out_uint16_le(s, 0);
393                    }
394                    if (0 < len_program)
395                    {
396                            rdp_out_unistr(s, program, len_program);
397    
398          out_uint32(s, 0);                  }
399          out_uint32_le(s, flags);                  else
400          out_uint16_le(s, len_domain);                  {
401          out_uint16_le(s, len_user);                          out_uint16_le(s, 0);
402          out_uint16_le(s, len_password);                  }
403          out_uint16_le(s, len_program);                  if (0 < len_directory)
404          out_uint16_le(s, len_directory);                  {
405          rdp_out_unistr(s, domain, len_domain);                          rdp_out_unistr(s, directory, len_directory);
406          rdp_out_unistr(s, user, len_user);                  }
407          rdp_out_unistr(s, password, len_password);                  else
408          rdp_out_unistr(s, program, len_program);                  {
409          rdp_out_unistr(s, directory, len_directory);                          out_uint16_le(s, 0);
410                    }
411                    out_uint16_le(s, 2);
412                    out_uint16_le(s, len_ip + 2);   /* Length of client ip */
413                    rdp_out_unistr(s, ipaddr, len_ip);
414                    out_uint16_le(s, len_dll + 2);
415                    rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
416    
417                    tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
418                    out_uint32_le(s, tzone);
419    
420                    rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
421                    out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
422    
423                    out_uint32_le(s, 0x0a0000);
424                    out_uint32_le(s, 0x050000);
425                    out_uint32_le(s, 3);
426                    out_uint32_le(s, 0);
427                    out_uint32_le(s, 0);
428    
429                    rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
430                    out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
431    
432                    out_uint32_le(s, 0x30000);
433                    out_uint32_le(s, 0x050000);
434                    out_uint32_le(s, 2);
435                    out_uint32(s, 0);
436                    out_uint32_le(s, 0xffffffc4);
437                    out_uint32_le(s, 0xfffffffe);
438                    out_uint32_le(s, g_rdp5_performanceflags);
439                    out_uint32(s, 0);
440    
441    
442            }
443          s_mark_end(s);          s_mark_end(s);
444          sec_send(s, sec_flags);          sec_send(s, sec_flags);
445  }  }
446    
447  /* Send a control PDU */  /* Send a control PDU */
448  static void rdp_send_control(uint16 action)  static void
449    rdp_send_control(uint16 action)
450  {  {
451          STREAM s;          STREAM s;
452    
# Line 186  static void rdp_send_control(uint16 acti Line 461  static void rdp_send_control(uint16 acti
461  }  }
462    
463  /* Send a synchronisation PDU */  /* Send a synchronisation PDU */
464  static void rdp_send_synchronise()  static void
465    rdp_send_synchronise(void)
466  {  {
467          STREAM s;          STREAM s;
468    
# Line 200  static void rdp_send_synchronise() Line 476  static void rdp_send_synchronise()
476  }  }
477    
478  /* Send a single input event */  /* Send a single input event */
479  void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags,  void
480                      uint16 param1, uint16 param2)  rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
481  {  {
482          STREAM s;          STREAM s;
483    
# Line 220  void rdp_send_input(uint32 time, uint16 Line 496  void rdp_send_input(uint32 time, uint16
496          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
497  }  }
498    
499    /* Send a client window information PDU */
500    void
501    rdp_send_client_window_status(int status)
502    {
503            STREAM s;
504            static int current_status = 1;
505    
506            if (current_status == status)
507                    return;
508    
509            s = rdp_init_data(12);
510    
511            out_uint32_le(s, status);
512    
513            switch (status)
514            {
515                    case 0: /* shut the server up */
516                            break;
517    
518                    case 1: /* receive data again */
519                            out_uint32_le(s, 0);    /* unknown */
520                            out_uint16_le(s, g_width);
521                            out_uint16_le(s, g_height);
522                            break;
523            }
524    
525            s_mark_end(s);
526            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
527            current_status = status;
528    }
529    
530    /* Send persistent bitmap cache enumeration PDU's */
531    static void
532    rdp_enum_bmpcache2(void)
533    {
534            STREAM s;
535            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
536            uint32 num_keys, offset, count, flags;
537    
538            offset = 0;
539            num_keys = pstcache_enumerate(2, keylist);
540    
541            while (offset < num_keys)
542            {
543                    count = MIN(num_keys - offset, 169);
544    
545                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
546    
547                    flags = 0;
548                    if (offset == 0)
549                            flags |= PDU_FLAG_FIRST;
550                    if (num_keys - offset <= 169)
551                            flags |= PDU_FLAG_LAST;
552    
553                    /* header */
554                    out_uint32_le(s, 0);
555                    out_uint16_le(s, count);
556                    out_uint16_le(s, 0);
557                    out_uint16_le(s, 0);
558                    out_uint16_le(s, 0);
559                    out_uint16_le(s, 0);
560                    out_uint16_le(s, num_keys);
561                    out_uint32_le(s, 0);
562                    out_uint32_le(s, flags);
563    
564                    /* list */
565                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
566    
567                    s_mark_end(s);
568                    rdp_send_data(s, 0x2b);
569    
570                    offset += 169;
571            }
572    }
573    
574  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
575  static void rdp_send_fonts(uint16 seq)  static void
576    rdp_send_fonts(uint16 seq)
577  {  {
578          STREAM s;          STREAM s;
579    
580          s = rdp_init_data(8);          s = rdp_init_data(8);
581    
582          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
583          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
584          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
585          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
586    
# Line 237  static void rdp_send_fonts(uint16 seq) Line 589  static void rdp_send_fonts(uint16 seq)
589  }  }
590    
591  /* Output general capability set */  /* Output general capability set */
592  static void rdp_out_general_caps(STREAM s)  static void
593    rdp_out_general_caps(STREAM s)
594  {  {
595          out_uint16_le(s, RDP_CAPSET_GENERAL);          out_uint16_le(s, RDP_CAPSET_GENERAL);
596          out_uint16_le(s, RDP_CAPLEN_GENERAL);          out_uint16_le(s, RDP_CAPLEN_GENERAL);
# Line 247  static void rdp_out_general_caps(STREAM Line 600  static void rdp_out_general_caps(STREAM
600          out_uint16_le(s, 0x200);        /* Protocol version */          out_uint16_le(s, 0x200);        /* Protocol version */
601          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
602          out_uint16(s, 0);       /* Compression types */          out_uint16(s, 0);       /* Compression types */
603          out_uint16(s, 0);       /* Pad */          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
604            /* Pad, according to T.128. 0x40d seems to
605               trigger
606               the server to start sending RDP5 packets.
607               However, the value is 0x1d04 with W2KTSK and
608               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
609               for sending such information in a padding
610               field.. */
611          out_uint16(s, 0);       /* Update capability */          out_uint16(s, 0);       /* Update capability */
612          out_uint16(s, 0);       /* Remote unshare capability */          out_uint16(s, 0);       /* Remote unshare capability */
613          out_uint16(s, 0);       /* Compression level */          out_uint16(s, 0);       /* Compression level */
# Line 255  static void rdp_out_general_caps(STREAM Line 615  static void rdp_out_general_caps(STREAM
615  }  }
616    
617  /* Output bitmap capability set */  /* Output bitmap capability set */
618  static void rdp_out_bitmap_caps(STREAM s)  static void
619    rdp_out_bitmap_caps(STREAM s)
620  {  {
621          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
622          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
623    
624          out_uint16_le(s, 8);    /* Preferred BPP */          out_uint16_le(s, g_server_depth);       /* Preferred colour depth */
625          out_uint16(s, 1);       /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
626          out_uint16(s, 1);       /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
627          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
628          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
629          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
630          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
631          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
632          out_uint16_le(s, 1);    /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
633          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
634          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
635          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
636  }  }
637    
638  /* Output order capability set */  /* Output order capability set */
639  static void rdp_out_order_caps(STREAM s)  static void
640    rdp_out_order_caps(STREAM s)
641  {  {
642          uint8 order_caps[32];          uint8 order_caps[32];
643    
644          memset(order_caps, orders, 32);          memset(order_caps, 0, 32);
645            order_caps[0] = 1;      /* dest blt */
646            order_caps[1] = 1;      /* pat blt */
647            order_caps[2] = 1;      /* screen blt */
648            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
649            order_caps[4] = 0;      /* triblt */
650            order_caps[8] = 1;      /* line */
651            order_caps[9] = 1;      /* line */
652            order_caps[10] = 1;     /* rect */
653            order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
654            order_caps[13] = 1;     /* memblt */
655            order_caps[14] = 1;     /* triblt */
656            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
657            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
658            order_caps[22] = 1;     /* polyline */
659            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
660            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
661            order_caps[27] = 1;     /* text2 */
662          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
663          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
664    
# Line 294  static void rdp_out_order_caps(STREAM s) Line 672  static void rdp_out_order_caps(STREAM s)
672          out_uint8p(s, order_caps, 32);  /* Orders supported */          out_uint8p(s, order_caps, 32);  /* Orders supported */
673          out_uint16_le(s, 0x6a1);        /* Text capability flags */          out_uint16_le(s, 0x6a1);        /* Text capability flags */
674          out_uint8s(s, 6);       /* Pad */          out_uint8s(s, 6);       /* Pad */
675          out_uint32(s, 0x38400); /* Desktop cache size */          out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
676          out_uint32(s, 0);       /* Unknown */          out_uint32(s, 0);       /* Unknown */
677          out_uint32(s, 0x4e4);   /* Unknown */          out_uint32_le(s, 0x4e4);        /* Unknown */
678  }  }
679    
680  /* Output bitmap cache capability set */  /* Output bitmap cache capability set */
681  static void rdp_out_bmpcache_caps(STREAM s)  static void
682    rdp_out_bmpcache_caps(STREAM s)
683  {  {
684            int Bpp;
685          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
686          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
687    
688            Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
689          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
690          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
691          out_uint16_le(s, 0x100);        /* max cell size */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
692          out_uint16_le(s, 0x12c);        /* entries */          out_uint16_le(s, 0x12c);        /* entries */
693          out_uint16_le(s, 0x400);        /* max cell size */          out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
694          out_uint16_le(s, 0x106);        /* entries */          out_uint16_le(s, 0x106);        /* entries */
695          out_uint16_le(s, 0x1000);       /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
696    }
697    
698    /* Output bitmap cache v2 capability set */
699    static void
700    rdp_out_bmpcache2_caps(STREAM s)
701    {
702            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
703            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
704    
705            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
706    
707            out_uint16_be(s, 3);    /* number of caches in this set */
708    
709            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
710            out_uint32_le(s, BMPCACHE2_C0_CELLS);
711            out_uint32_le(s, BMPCACHE2_C1_CELLS);
712            if (pstcache_init(2))
713            {
714                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
715            }
716            else
717            {
718                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
719            }
720            out_uint8s(s, 20);      /* other bitmap caches not used */
721  }  }
722    
723  /* Output control capability set */  /* Output control capability set */
724  static void rdp_out_control_caps(STREAM s)  static void
725    rdp_out_control_caps(STREAM s)
726  {  {
727          out_uint16_le(s, RDP_CAPSET_CONTROL);          out_uint16_le(s, RDP_CAPSET_CONTROL);
728          out_uint16_le(s, RDP_CAPLEN_CONTROL);          out_uint16_le(s, RDP_CAPLEN_CONTROL);
# Line 327  static void rdp_out_control_caps(STREAM Line 734  static void rdp_out_control_caps(STREAM
734  }  }
735    
736  /* Output activation capability set */  /* Output activation capability set */
737  static void rdp_out_activate_caps(STREAM s)  static void
738    rdp_out_activate_caps(STREAM s)
739  {  {
740          out_uint16_le(s, RDP_CAPSET_ACTIVATE);          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
741          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
# Line 339  static void rdp_out_activate_caps(STREAM Line 747  static void rdp_out_activate_caps(STREAM
747  }  }
748    
749  /* Output pointer capability set */  /* Output pointer capability set */
750  static void rdp_out_pointer_caps(STREAM s)  static void
751    rdp_out_pointer_caps(STREAM s)
752  {  {
753          out_uint16_le(s, RDP_CAPSET_POINTER);          out_uint16_le(s, RDP_CAPSET_POINTER);
754          out_uint16_le(s, RDP_CAPLEN_POINTER);          out_uint16_le(s, RDP_CAPLEN_POINTER);
# Line 349  static void rdp_out_pointer_caps(STREAM Line 758  static void rdp_out_pointer_caps(STREAM
758  }  }
759    
760  /* Output share capability set */  /* Output share capability set */
761  static void rdp_out_share_caps(STREAM s)  static void
762    rdp_out_share_caps(STREAM s)
763  {  {
764          out_uint16_le(s, RDP_CAPSET_SHARE);          out_uint16_le(s, RDP_CAPSET_SHARE);
765          out_uint16_le(s, RDP_CAPLEN_SHARE);          out_uint16_le(s, RDP_CAPLEN_SHARE);
# Line 359  static void rdp_out_share_caps(STREAM s) Line 769  static void rdp_out_share_caps(STREAM s)
769  }  }
770    
771  /* Output colour cache capability set */  /* Output colour cache capability set */
772  static void rdp_out_colcache_caps(STREAM s)  static void
773    rdp_out_colcache_caps(STREAM s)
774  {  {
775          out_uint16_le(s, RDP_CAPSET_COLCACHE);          out_uint16_le(s, RDP_CAPSET_COLCACHE);
776          out_uint16_le(s, RDP_CAPLEN_COLCACHE);          out_uint16_le(s, RDP_CAPLEN_COLCACHE);
# Line 368  static void rdp_out_colcache_caps(STREAM Line 779  static void rdp_out_colcache_caps(STREAM
779          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
780  }  }
781    
782  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
783          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
784          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785                  0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787                  0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789                  0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791                  0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793                  0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
794          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  };
795                  0x10, 0x00, 0x34, 0x00, 0xFE,  
796          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
797                  0xFE, 0x00, 0x08, 0x00, 0xFE,  
798          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
799                  0xFE, 0x00, 0x80, 0x00, 0xFE,  
800          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  static uint8 caps_0x10[] = {
801                  0x02, 0x00, 0x00, 0x00          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
802            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
803            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
804            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
805            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
806            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
807  };  };
808    
809  /* Output unknown capability set */  /* Output unknown capability sets */
810  static void rdp_out_unknown_caps(STREAM s)  static void
811    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
812  {  {
813          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
814          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
815    
816          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
817  }  }
818    
819    #define RDP5_FLAG 0x0030
820  /* Send a confirm active PDU */  /* Send a confirm active PDU */
821  static void rdp_send_confirm_active()  static void
822    rdp_send_confirm_active(void)
823  {  {
824          STREAM s;          STREAM s;
825            uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
826          uint16 caplen =          uint16 caplen =
827                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
828                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
829                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
830                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
831                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
832                    4 /* w2k fix, why? */ ;
833    
834            s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
835    
836          s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
837            out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
838            out_uint16_le(s, (g_mcs_userid + 1001));
839    
840          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
841          out_uint16_le(s, 0x3ea);        /* userid */          out_uint16_le(s, 0x3ea);        /* userid */
842          out_uint16_le(s, sizeof(RDP_SOURCE));          out_uint16_le(s, sizeof(RDP_SOURCE));
843          out_uint16_le(s, caplen);          out_uint16_le(s, caplen);
# Line 423  static void rdp_send_confirm_active() Line 849  static void rdp_send_confirm_active()
849          rdp_out_general_caps(s);          rdp_out_general_caps(s);
850          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
851          rdp_out_order_caps(s);          rdp_out_order_caps(s);
852          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
853          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
854          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
855          rdp_out_control_caps(s);          rdp_out_control_caps(s);
856          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
857          rdp_out_share_caps(s);          rdp_out_share_caps(s);
858          rdp_out_unknown_caps(s);  
859            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
860            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
861            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
862            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
863    
864          s_mark_end(s);          s_mark_end(s);
865          rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);          sec_send(s, sec_flags);
866    }
867    
868    /* Process a general capability set */
869    static void
870    rdp_process_general_caps(STREAM s)
871    {
872            uint16 pad2octetsB;     /* rdp5 flags? */
873    
874            in_uint8s(s, 10);
875            in_uint16_le(s, pad2octetsB);
876    
877            if (!pad2octetsB)
878                    g_use_rdp5 = False;
879    }
880    
881    /* Process a bitmap capability set */
882    static void
883    rdp_process_bitmap_caps(STREAM s)
884    {
885            uint16 width, height, depth;
886    
887            in_uint16_le(s, depth);
888            in_uint8s(s, 6);
889    
890            in_uint16_le(s, width);
891            in_uint16_le(s, height);
892    
893            DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
894    
895            /*
896             * The server may limit depth and change the size of the desktop (for
897             * example when shadowing another session).
898             */
899            if (g_server_depth != depth)
900            {
901                    warning("Remote desktop does not support colour depth %d; falling back to %d\n",
902                            g_server_depth, depth);
903                    g_server_depth = depth;
904            }
905            if (g_width != width || g_height != height)
906            {
907                    warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
908                            width, height);
909                    g_width = width;
910                    g_height = height;
911                    ui_resize_window();
912            }
913    }
914    
915    /* Process server capabilities */
916    static void
917    rdp_process_server_caps(STREAM s, uint16 length)
918    {
919            int n;
920            uint8 *next, *start;
921            uint16 ncapsets, capset_type, capset_length;
922    
923            start = s->p;
924    
925            in_uint16_le(s, ncapsets);
926            in_uint8s(s, 2);        /* pad */
927    
928            for (n = 0; n < ncapsets; n++)
929            {
930                    if (s->p > start + length)
931                            return;
932    
933                    in_uint16_le(s, capset_type);
934                    in_uint16_le(s, capset_length);
935    
936                    next = s->p + capset_length - 4;
937    
938                    switch (capset_type)
939                    {
940                            case RDP_CAPSET_GENERAL:
941                                    rdp_process_general_caps(s);
942                                    break;
943    
944                            case RDP_CAPSET_BITMAP:
945                                    rdp_process_bitmap_caps(s);
946                                    break;
947                    }
948    
949                    s->p = next;
950            }
951  }  }
952    
953  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
954  static void process_demand_active(STREAM s)  static void
955    process_demand_active(STREAM s)
956  {  {
957          uint8 type;          uint8 type;
958            uint16 len_src_descriptor, len_combined_caps;
959    
960          in_uint32_le(s, rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
961            in_uint16_le(s, len_src_descriptor);
962            in_uint16_le(s, len_combined_caps);
963            in_uint8s(s, len_src_descriptor);
964    
965          DEBUG("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid);          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
966            rdp_process_server_caps(s, len_combined_caps);
967    
968          rdp_send_confirm_active();          rdp_send_confirm_active();
969          rdp_send_synchronise();          rdp_send_synchronise();
970          rdp_send_control(RDP_CTL_COOPERATE);          rdp_send_control(RDP_CTL_COOPERATE);
971          rdp_send_control(RDP_CTL_REQUEST_CONTROL);          rdp_send_control(RDP_CTL_REQUEST_CONTROL);
972          rdp_recv(&type);        // RDP_PDU_SYNCHRONIZE          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
973          rdp_recv(&type);        // RDP_CTL_COOPERATE          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
974          rdp_recv(&type);        // RDP_CTL_GRANT_CONTROL          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
975          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
976          rdp_send_fonts(1);                         g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
977          rdp_send_fonts(2);  
978          rdp_recv(&type);        // RDP_PDU_UNKNOWN 0x28          if (g_use_rdp5)
979            {
980                    rdp_enum_bmpcache2();
981                    rdp_send_fonts(3);
982            }
983            else
984            {
985                    rdp_send_fonts(1);
986                    rdp_send_fonts(2);
987            }
988    
989            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
990          reset_order_state();          reset_order_state();
991  }  }
992    
993    /* Process a colour pointer PDU */
994    void
995    process_colour_pointer_pdu(STREAM s)
996    {
997            uint16 x, y, width, height, cache_idx, masklen, datalen;
998            uint8 *mask, *data;
999            HCURSOR cursor;
1000    
1001            in_uint16_le(s, cache_idx);
1002            in_uint16_le(s, x);
1003            in_uint16_le(s, y);
1004            in_uint16_le(s, width);
1005            in_uint16_le(s, height);
1006            in_uint16_le(s, masklen);
1007            in_uint16_le(s, datalen);
1008            in_uint8p(s, data, datalen);
1009            in_uint8p(s, mask, masklen);
1010            cursor = ui_create_cursor(x, y, width, height, mask, data);
1011            ui_set_cursor(cursor);
1012            cache_put_cursor(cache_idx, cursor);
1013    }
1014    
1015    /* Process a cached pointer PDU */
1016    void
1017    process_cached_pointer_pdu(STREAM s)
1018    {
1019            uint16 cache_idx;
1020    
1021            in_uint16_le(s, cache_idx);
1022            ui_set_cursor(cache_get_cursor(cache_idx));
1023    }
1024    
1025    /* Process a system pointer PDU */
1026    void
1027    process_system_pointer_pdu(STREAM s)
1028    {
1029            uint16 system_pointer_type;
1030    
1031            in_uint16(s, system_pointer_type);
1032            switch (system_pointer_type)
1033            {
1034                    case RDP_NULL_POINTER:
1035                            ui_set_null_cursor();
1036                            break;
1037    
1038                    default:
1039                            unimpl("System pointer message 0x%x\n", system_pointer_type);
1040            }
1041    }
1042    
1043  /* Process a pointer PDU */  /* Process a pointer PDU */
1044  static void process_pointer_pdu(STREAM s)  static void
1045    process_pointer_pdu(STREAM s)
1046  {  {
1047          uint16 message_type;          uint16 message_type;
1048          uint16 x, y;          uint16 x, y;
# Line 476  static void process_pointer_pdu(STREAM s Line 1059  static void process_pointer_pdu(STREAM s
1059                                  ui_move_pointer(x, y);                                  ui_move_pointer(x, y);
1060                          break;                          break;
1061    
1062                    case RDP_POINTER_COLOR:
1063                            process_colour_pointer_pdu(s);
1064                            break;
1065    
1066                    case RDP_POINTER_CACHED:
1067                            process_cached_pointer_pdu(s);
1068                            break;
1069    
1070                    case RDP_POINTER_SYSTEM:
1071                            process_system_pointer_pdu(s);
1072                            break;
1073    
1074                  default:                  default:
1075                          DEBUG("Pointer message 0x%x\n", message_type);                          unimpl("Pointer message 0x%x\n", message_type);
1076          }          }
1077  }  }
1078    
1079  /* Process bitmap updates */  /* Process bitmap updates */
1080  static void process_bitmap_updates(STREAM s)  void
1081    process_bitmap_updates(STREAM s)
1082  {  {
1083          uint16 num_updates;          uint16 num_updates;
1084          uint16 left, top, right, bottom, width, height;          uint16 left, top, right, bottom, width, height;
1085          uint16 cx, cy, bpp, compress, bufsize, size;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1086          uint8 *data, *rawdata;          uint8 *data, *bmpdata;
1087          int i;          int i;
1088    
1089          in_uint16_le(s, num_updates);          in_uint16_le(s, num_updates);
# Line 501  static void process_bitmap_updates(STREA Line 1097  static void process_bitmap_updates(STREA
1097                  in_uint16_le(s, width);                  in_uint16_le(s, width);
1098                  in_uint16_le(s, height);                  in_uint16_le(s, height);
1099                  in_uint16_le(s, bpp);                  in_uint16_le(s, bpp);
1100                    Bpp = (bpp + 7) / 8;
1101                  in_uint16_le(s, compress);                  in_uint16_le(s, compress);
1102                  in_uint16_le(s, bufsize);                  in_uint16_le(s, bufsize);
1103    
1104                  cx = right - left + 1;                  cx = right - left + 1;
1105                  cy = bottom - top + 1;                  cy = bottom - top + 1;
1106    
1107                  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",
1108                        left, top, right, bottom, width, height, compress);                         left, top, right, bottom, width, height, Bpp, compress));
1109    
1110                  if (!compress)                  if (!compress)
1111                  {                  {
1112                          in_uint8p(s, data, bufsize);                          int y;
1113                          ui_paint_bitmap(left, top, cx, cy, width, height,                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1114                                          data);                          for (y = 0; y < height; y++)
1115                          return;                          {
1116                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1117                                              width * Bpp);
1118                            }
1119                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1120                            xfree(bmpdata);
1121                            continue;
1122                  }                  }
1123    
                 in_uint8s(s, 2);        /* pad */  
                 in_uint16_le(s, size);  
                 in_uint8s(s, 4);        /* line_size, final_size */  
                 in_uint8p(s, data, size);  
1124    
1125                  rawdata = xmalloc(width * height);                  if (compress & 0x400)
1126                  if (bitmap_decompress(rawdata, width, height, data, size))                  {
1127                            size = bufsize;
1128                    }
1129                    else
1130                  {                  {
1131                          ui_paint_bitmap(left, top, cx, cy, width, height,                          in_uint8s(s, 2);        /* pad */
1132                                          rawdata);                          in_uint16_le(s, size);
1133                            in_uint8s(s, 4);        /* line_size, final_size */
1134                    }
1135                    in_uint8p(s, data, size);
1136                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1137                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1138                    {
1139                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1140                    }
1141                    else
1142                    {
1143                            DEBUG_RDP5(("Failed to decompress data\n"));
1144                  }                  }
1145    
1146                  xfree(rawdata);                  xfree(bmpdata);
1147          }          }
1148  }  }
1149    
1150  /* Process a palette update */  /* Process a palette update */
1151  static void process_palette(STREAM s)  void
1152    process_palette(STREAM s)
1153  {  {
1154          HCOLOURMAP hmap;          COLOURENTRY *entry;
1155          COLOURMAP map;          COLOURMAP map;
1156            HCOLOURMAP hmap;
1157            int i;
1158    
1159          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1160          in_uint16_le(s, map.ncolours);          in_uint16_le(s, map.ncolours);
1161          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1162          in_uint8p(s, (uint8 *) map.colours, (map.ncolours * 3));  
1163            map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1164    
1165            DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1166    
1167            for (i = 0; i < map.ncolours; i++)
1168            {
1169                    entry = &map.colours[i];
1170                    in_uint8(s, entry->red);
1171                    in_uint8(s, entry->green);
1172                    in_uint8(s, entry->blue);
1173            }
1174    
1175          hmap = ui_create_colourmap(&map);          hmap = ui_create_colourmap(&map);
1176          ui_set_colourmap(hmap);          ui_set_colourmap(hmap);
1177    
1178            xfree(map.colours);
1179  }  }
1180    
1181  /* Process an update PDU */  /* Process an update PDU */
1182  static void process_update_pdu(STREAM s)  static void
1183    process_update_pdu(STREAM s)
1184  {  {
1185          uint16 update_type;          uint16 update_type, count;
1186    
1187          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1188    
1189            ui_begin_update();
1190          switch (update_type)          switch (update_type)
1191          {          {
1192                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
1193                          process_orders(s);                          in_uint8s(s, 2);        /* pad */
1194                            in_uint16_le(s, count);
1195                            in_uint8s(s, 2);        /* pad */
1196                            process_orders(s, count);
1197                          break;                          break;
1198    
1199                  case RDP_UPDATE_BITMAP:                  case RDP_UPDATE_BITMAP:
# Line 574  static void process_update_pdu(STREAM s) Line 1208  static void process_update_pdu(STREAM s)
1208                          break;                          break;
1209    
1210                  default:                  default:
1211                          NOTIMP("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1212          }          }
1213            ui_end_update();
1214    }
1215    
1216    /* Process a disconnect PDU */
1217    void
1218    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1219    {
1220            in_uint32_le(s, *ext_disc_reason);
1221    
1222            DEBUG(("Received disconnect PDU\n"));
1223  }  }
1224    
1225  /* Process data PDU */  /* Process data PDU */
1226  static void process_data_pdu(STREAM s)  static BOOL
1227    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1228  {  {
1229          uint8 data_pdu_type;          uint8 data_pdu_type;
1230            uint8 ctype;
1231            uint16 clen;
1232            uint32 len;
1233    
1234            uint32 roff, rlen;
1235    
1236          in_uint8s(s, 8);        /* shareid, pad, streamid, length */          struct stream *ns = &(g_mppc_dict.ns);
1237    
1238            in_uint8s(s, 6);        /* shareid, pad, streamid */
1239            in_uint16(s, len);
1240          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1241          in_uint8s(s, 3);        /* compress_type, compress_len */          in_uint8(s, ctype);
1242            in_uint16(s, clen);
1243            clen -= 18;
1244    
1245            if (ctype & RDP_MPPC_COMPRESSED)
1246            {
1247                    if (len > RDP_MPPC_DICT_SIZE)
1248                            error("error decompressed packet size exceeds max\n");
1249                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1250                            error("error while decompressing packet\n");
1251    
1252                    /* len -= 18; */
1253    
1254                    /* allocate memory and copy the uncompressed data into the temporary stream */
1255                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1256    
1257                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1258    
1259                    ns->size = rlen;
1260                    ns->end = (ns->data + ns->size);
1261                    ns->p = ns->data;
1262                    ns->rdp_hdr = ns->p;
1263    
1264                    s = ns;
1265            }
1266    
1267          switch (data_pdu_type)          switch (data_pdu_type)
1268          {          {
# Line 594  static void process_data_pdu(STREAM s) Line 1270  static void process_data_pdu(STREAM s)
1270                          process_update_pdu(s);                          process_update_pdu(s);
1271                          break;                          break;
1272    
1273                    case RDP_DATA_PDU_CONTROL:
1274                            DEBUG(("Received Control PDU\n"));
1275                            break;
1276    
1277                    case RDP_DATA_PDU_SYNCHRONISE:
1278                            DEBUG(("Received Sync PDU\n"));
1279                            break;
1280    
1281                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1282                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1283                          break;                          break;
# Line 603  static void process_data_pdu(STREAM s) Line 1287  static void process_data_pdu(STREAM s)
1287                          break;                          break;
1288    
1289                  case RDP_DATA_PDU_LOGON:                  case RDP_DATA_PDU_LOGON:
1290                            DEBUG(("Received Logon PDU\n"));
1291                          /* User logged on */                          /* User logged on */
1292                          break;                          break;
1293    
1294                    case RDP_DATA_PDU_DISCONNECT:
1295                            process_disconnect_pdu(s, ext_disc_reason);
1296    
1297                            /* We used to return true and disconnect immediately here, but
1298                             * Windows Vista sends a disconnect PDU with reason 0 when
1299                             * reconnecting to a disconnected session, and MSTSC doesn't
1300                             * drop the connection.  I think we should just save the status.
1301                             */
1302                            break;
1303    
1304                  default:                  default:
1305                          NOTIMP("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1306          }          }
1307            return False;
1308    }
1309    
1310    /* Process redirect PDU from Session Directory */
1311    static BOOL
1312    process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1313    {
1314            uint32 len;
1315    
1316            /* these 2 bytes are unknown, seem to be zeros */
1317            in_uint8s(s, 2);
1318    
1319            /* read connection flags */
1320            in_uint32_le(s, g_redirect_flags);
1321    
1322            /* read length of ip string */
1323            in_uint32_le(s, len);
1324    
1325            /* read ip string */
1326            rdp_in_unistr(s, g_redirect_server, len);
1327    
1328            /* read length of cookie string */
1329            in_uint32_le(s, len);
1330    
1331            /* read cookie string (plain ASCII) */
1332            in_uint8a(s, g_redirect_cookie, len);
1333            g_redirect_cookie[len] = 0;
1334    
1335            /* read length of username string */
1336            in_uint32_le(s, len);
1337    
1338            /* read username string */
1339            rdp_in_unistr(s, g_redirect_username, len);
1340    
1341            /* read length of domain string */
1342            in_uint32_le(s, len);
1343    
1344            /* read domain string */
1345            rdp_in_unistr(s, g_redirect_domain, len);
1346    
1347            /* read length of password string */
1348            in_uint32_le(s, len);
1349    
1350            /* read password string */
1351            rdp_in_unistr(s, g_redirect_password, len);
1352    
1353            g_redirect = True;
1354    
1355            return True;
1356  }  }
1357    
1358  /* Process incoming packets */  /* Process incoming packets */
1359  void rdp_main_loop()  /* nevers gets out of here till app is done */
1360    void
1361    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1362    {
1363            while (rdp_loop(deactivated, ext_disc_reason))
1364                    ;
1365    }
1366    
1367    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1368    BOOL
1369    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1370  {  {
1371          uint8 type;          uint8 type;
1372            BOOL disc = False;      /* True when a disconnect PDU was received */
1373            BOOL cont = True;
1374          STREAM s;          STREAM s;
1375    
1376          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1377          {          {
1378                    s = rdp_recv(&type);
1379                    if (s == NULL)
1380                            return False;
1381                  switch (type)                  switch (type)
1382                  {                  {
1383                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1384                                  process_demand_active(s);                                  process_demand_active(s);
1385                                    *deactivated = False;
1386                                  break;                                  break;
   
1387                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1388                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1389                                    *deactivated = True;
1390                                    break;
1391                            case RDP_PDU_REDIRECT:
1392                                    return process_redirect_pdu(s);
1393                                  break;                                  break;
   
1394                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1395                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1396                                    break;
1397                            case 0:
1398                                  break;                                  break;
   
1399                          default:                          default:
1400                                  NOTIMP("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1401                  }                  }
1402                    if (disc)
1403                            return False;
1404                    cont = g_next_packet < s->end;
1405          }          }
1406            return True;
1407  }  }
1408    
1409  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
1410  BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password,  BOOL
1411                   char *command, char *directory)  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1412                char *command, char *directory)
1413  {  {
1414          if (!sec_connect(server))          if (!sec_connect(server, g_username))
1415                  return False;                  return False;
1416    
1417          rdp_send_logon_info(flags, domain, username, password,          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
                             command, directory);  
1418          return True;          return True;
1419  }  }
1420    
1421    /* Establish a reconnection up to the RDP layer */
1422    BOOL
1423    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1424                  char *command, char *directory, char *cookie)
1425    {
1426            if (!sec_reconnect(server))
1427                    return False;
1428    
1429            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1430            return True;
1431    }
1432    
1433    /* Called during redirection to reset the state to support redirection */
1434    void
1435    rdp_reset_state(void)
1436    {
1437            g_next_packet = NULL;   /* reset the packet information */
1438            g_rdp_shareid = 0;
1439            sec_reset_state();
1440    }
1441    
1442  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1443  void rdp_disconnect()  void
1444    rdp_disconnect(void)
1445  {  {
1446          sec_disconnect();          sec_disconnect();
1447  }  }

Legend:
Removed from v.24  
changed lines
  Added in v.1238

  ViewVC Help
Powered by ViewVC 1.1.26