/[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 562 by stargo, Thu Dec 11 17:20:01 2003 UTC revision 945 by astrand, Tue Aug 2 09:29:41 2005 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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-2002     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
# Line 19  Line 19 
19  */  */
20    
21  #include <time.h>  #include <time.h>
22    #include <errno.h>
23    #include <unistd.h>
24  #include "rdesktop.h"  #include "rdesktop.h"
25    
26    #ifdef HAVE_ICONV
27    #ifdef HAVE_ICONV_H
28    #include <iconv.h>
29    #endif
30    
31    #ifndef ICONV_CONST
32    #define ICONV_CONST ""
33    #endif
34    #endif
35    
36  extern uint16 g_mcs_userid;  extern uint16 g_mcs_userid;
37  extern char g_username[16];  extern char g_username[64];
38    extern char g_codepage[16];
39  extern BOOL g_bitmap_compression;  extern BOOL g_bitmap_compression;
40  extern BOOL g_orders;  extern BOOL g_orders;
41  extern BOOL g_encryption;  extern BOOL g_encryption;
42  extern BOOL g_desktop_save;  extern BOOL g_desktop_save;
43    extern BOOL g_polygon_ellipse_orders;
44  extern BOOL g_use_rdp5;  extern BOOL g_use_rdp5;
45  extern uint16 g_server_rdp_version;  extern uint16 g_server_rdp_version;
46    extern uint32 g_rdp5_performanceflags;
47  extern int g_server_bpp;  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  uint8 *g_next_packet;  uint8 *g_next_packet;
54  uint32 g_rdp_shareid;  uint32 g_rdp_shareid;
55    
56    extern RDPCOMP g_mppc_dict;
57    
58  #if WITH_DEBUG  #if WITH_DEBUG
59  static uint32 g_packetno;  static uint32 g_packetno;
60  #endif  #endif
61    
62    #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  static STREAM
68  rdp_recv(uint8 * type)  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) || (g_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                  g_next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
94          }          }
# Line 119  rdp_send_data(STREAM s, uint8 data_pdu_t Line 158  rdp_send_data(STREAM s, uint8 data_pdu_t
158  void  void
159  rdp_out_unistr(STREAM s, char *string, int len)  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;
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          s->p += len;                  return i - 1;
277            }
278  }  }
279    
280    
281  /* Parse a logon info packet */  /* Parse a logon info packet */
282  static void  static void
283  rdp_send_logon_info(uint32 flags, char *domain, char *user,  rdp_send_logon_info(uint32 flags, char *domain, char *user,
284                      char *password, char *program, char *directory)                      char *password, char *program, char *directory)
285  {  {
286            char *ipaddr = tcp_get_address();
287          int len_domain = 2 * strlen(domain);          int len_domain = 2 * strlen(domain);
288          int len_user = 2 * strlen(user);          int len_user = 2 * strlen(user);
289          int len_password = 2 * strlen(password);          int len_password = 2 * strlen(password);
290          int len_program = 2 * strlen(program);          int len_program = 2 * strlen(program);
291          int len_directory = 2 * strlen(directory);          int len_directory = 2 * strlen(directory);
292          int len_ip = 2 * strlen("127.0.0.1");          int len_ip = 2 * strlen(ipaddr);
293          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
294          int packetlen = 0;          int packetlen = 0;
295          uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;          uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
# Line 172  rdp_send_logon_info(uint32 flags, char * Line 319  rdp_send_logon_info(uint32 flags, char *
319          }          }
320          else          else
321          {          {
322    
323                  flags |= RDP_LOGON_BLOB;                  flags |= RDP_LOGON_BLOB;
324                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
325                  packetlen = 4 + /* Unknown uint32 */                  packetlen = 4 + /* Unknown uint32 */
# Line 247  rdp_send_logon_info(uint32 flags, char * Line 395  rdp_send_logon_info(uint32 flags, char *
395                  }                  }
396                  out_uint16_le(s, 2);                  out_uint16_le(s, 2);
397                  out_uint16_le(s, len_ip + 2);   /* Length of client ip */                  out_uint16_le(s, len_ip + 2);   /* Length of client ip */
398                  rdp_out_unistr(s, "127.0.0.1", len_ip);                  rdp_out_unistr(s, ipaddr, len_ip);
399                  out_uint16_le(s, len_dll + 2);                  out_uint16_le(s, len_dll + 2);
400                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
401    
402                  tzone = (mktime(localtime(&t)) - mktime(gmtime(&t))) / 60;                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
403                  out_uint16_le(s, tzone);                  out_uint32_le(s, tzone);
                 out_uint16_le(s, 0x0000);  
404    
405                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
406                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
407    
   
408                  out_uint32_le(s, 0x0a0000);                  out_uint32_le(s, 0x0a0000);
409                  out_uint32_le(s, 0x050000);                  out_uint32_le(s, 0x050000);
410                  out_uint32_le(s, 3);                  out_uint32_le(s, 3);
# Line 274  rdp_send_logon_info(uint32 flags, char * Line 420  rdp_send_logon_info(uint32 flags, char *
420                  out_uint32(s, 0);                  out_uint32(s, 0);
421                  out_uint32_le(s, 0xffffffc4);                  out_uint32_le(s, 0xffffffc4);
422                  out_uint32_le(s, 0xfffffffe);                  out_uint32_le(s, 0xfffffffe);
423                  out_uint32_le(s, 0x0f);                  out_uint32_le(s, g_rdp5_performanceflags);
424                  out_uint32(s, 0);                  out_uint32(s, 0);
425    
426    
# Line 335  rdp_send_input(uint32 time, uint16 messa Line 481  rdp_send_input(uint32 time, uint16 messa
481          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
482  }  }
483    
484    /* Send a client window information PDU */
485    void
486    rdp_send_client_window_status(int status)
487    {
488            STREAM s;
489            static int current_status = 1;
490    
491            if (current_status == status)
492                    return;
493    
494            s = rdp_init_data(12);
495    
496            out_uint32_le(s, status);
497    
498            switch (status)
499            {
500                    case 0: /* shut the server up */
501                            break;
502    
503                    case 1: /* receive data again */
504                            out_uint32_le(s, 0);    /* unknown */
505                            out_uint16_le(s, g_width);
506                            out_uint16_le(s, g_height);
507                            break;
508            }
509    
510            s_mark_end(s);
511            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
512            current_status = status;
513    }
514    
515    /* Send persistent bitmap cache enumeration PDU's */
516    static void
517    rdp_enum_bmpcache2(void)
518    {
519            STREAM s;
520            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
521            uint32 num_keys, offset, count, flags;
522    
523            offset = 0;
524            num_keys = pstcache_enumerate(2, keylist);
525    
526            while (offset < num_keys)
527            {
528                    count = MIN(num_keys - offset, 169);
529    
530                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
531    
532                    flags = 0;
533                    if (offset == 0)
534                            flags |= PDU_FLAG_FIRST;
535                    if (num_keys - offset <= 169)
536                            flags |= PDU_FLAG_LAST;
537    
538                    /* header */
539                    out_uint32_le(s, 0);
540                    out_uint16_le(s, count);
541                    out_uint16_le(s, 0);
542                    out_uint16_le(s, 0);
543                    out_uint16_le(s, 0);
544                    out_uint16_le(s, 0);
545                    out_uint16_le(s, num_keys);
546                    out_uint32_le(s, 0);
547                    out_uint32_le(s, flags);
548    
549                    /* list */
550                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
551    
552                    s_mark_end(s);
553                    rdp_send_data(s, 0x2b);
554    
555                    offset += 169;
556            }
557    }
558    
559  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
560  static void  static void
561  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 344  rdp_send_fonts(uint16 seq) Line 565  rdp_send_fonts(uint16 seq)
565          s = rdp_init_data(8);          s = rdp_init_data(8);
566    
567          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
568          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
569          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
570          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
571    
# Line 385  rdp_out_bitmap_caps(STREAM s) Line 606  rdp_out_bitmap_caps(STREAM s)
606          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
607          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
608    
609          out_uint16_le(s, 8);    /* Preferred BPP */          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
610          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
611          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
612          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
613          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
614          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
615          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
616          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
617          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
618          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
619          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
# Line 405  rdp_out_order_caps(STREAM s) Line 626  rdp_out_order_caps(STREAM s)
626  {  {
627          uint8 order_caps[32];          uint8 order_caps[32];
628    
   
629          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
630          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
631          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
632          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
633          order_caps[3] = 1;      /* required for memblt? */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
634            order_caps[4] = 0;      /* triblt */
635          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
636          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
637          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
638          order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
639          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
640          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
641            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
642            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
643          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
644            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
645            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
646          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
647          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
648          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 455  rdp_out_bmpcache_caps(STREAM s) Line 680  rdp_out_bmpcache_caps(STREAM s)
680          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
681  }  }
682    
683    /* Output bitmap cache v2 capability set */
684    static void
685    rdp_out_bmpcache2_caps(STREAM s)
686    {
687            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
688            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
689    
690            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
691    
692            out_uint16_be(s, 3);    /* number of caches in this set */
693    
694            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
695            out_uint32_le(s, BMPCACHE2_C0_CELLS);
696            out_uint32_le(s, BMPCACHE2_C1_CELLS);
697            if (pstcache_init(2))
698            {
699                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
700            }
701            else
702            {
703                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
704            }
705            out_uint8s(s, 20);      /* other bitmap caches not used */
706    }
707    
708  /* Output control capability set */  /* Output control capability set */
709  static void  static void
710  rdp_out_control_caps(STREAM s)  rdp_out_control_caps(STREAM s)
# Line 514  rdp_out_colcache_caps(STREAM s) Line 764  rdp_out_colcache_caps(STREAM s)
764          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
765  }  }
766    
767  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
768          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
769          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
774          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
776          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
777          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778          0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
779          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  };
780          0x10, 0x00, 0x34, 0x00, 0xFE,  
781          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
782          0xFE, 0x00, 0x08, 0x00, 0xFE,  
783          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
784          0xFE, 0x00, 0x80, 0x00, 0xFE,  
785          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  static uint8 caps_0x10[] = {
786          0x02, 0x00, 0x00, 0x00          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
787            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
788            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
789            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
790            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
791            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
792  };  };
793    
794  /* Output unknown capability sets (number 13, 12, 14 and 16) */  /* Output unknown capability sets */
795  static void  static void
796  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
797  {  {
798          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
799          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
800    
801          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
802  }  }
803    
804  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 557  rdp_send_confirm_active(void) Line 812  rdp_send_confirm_active(void)
812                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
813                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
814                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
815                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
816                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
817                    4 /* w2k fix, why? */ ;
818    
819          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
820    
# Line 577  rdp_send_confirm_active(void) Line 834  rdp_send_confirm_active(void)
834          rdp_out_general_caps(s);          rdp_out_general_caps(s);
835          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
836          rdp_out_order_caps(s);          rdp_out_order_caps(s);
837          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
838          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
839          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
840          rdp_out_control_caps(s);          rdp_out_control_caps(s);
841          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
842          rdp_out_share_caps(s);          rdp_out_share_caps(s);
843          rdp_out_unknown_caps(s);  
844            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
845            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
846            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
847            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
848    
849          s_mark_end(s);          s_mark_end(s);
850          sec_send(s, sec_flags);          sec_send(s, sec_flags);
851  }  }
852    
853    /* Process a general capability set */
854    static void
855    rdp_process_general_caps(STREAM s)
856    {
857            uint16 pad2octetsB;     /* rdp5 flags? */
858    
859            in_uint8s(s, 10);
860            in_uint16_le(s, pad2octetsB);
861    
862            if (!pad2octetsB)
863                    g_use_rdp5 = False;
864    }
865    
866    /* Process a bitmap capability set */
867    static void
868    rdp_process_bitmap_caps(STREAM s)
869    {
870            uint16 width, height, bpp;
871    
872            in_uint16_le(s, bpp);
873            in_uint8s(s, 6);
874    
875            in_uint16_le(s, width);
876            in_uint16_le(s, height);
877    
878            DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
879    
880            /*
881             * The server may limit bpp and change the size of the desktop (for
882             * example when shadowing another session).
883             */
884            if (g_server_bpp != bpp)
885            {
886                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
887                    g_server_bpp = bpp;
888            }
889            if (g_width != width || g_height != height)
890            {
891                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
892                            width, height);
893                    g_width = width;
894                    g_height = height;
895                    ui_resize_window();
896            }
897    }
898    
899    /* Process server capabilities */
900    static void
901    rdp_process_server_caps(STREAM s, uint16 length)
902    {
903            int n;
904            uint8 *next, *start;
905            uint16 ncapsets, capset_type, capset_length;
906    
907            start = s->p;
908    
909            in_uint16_le(s, ncapsets);
910            in_uint8s(s, 2);        /* pad */
911    
912            for (n = 0; n < ncapsets; n++)
913            {
914                    if (s->p > start + length)
915                            return;
916    
917                    in_uint16_le(s, capset_type);
918                    in_uint16_le(s, capset_length);
919    
920                    next = s->p + capset_length - 4;
921    
922                    switch (capset_type)
923                    {
924                            case RDP_CAPSET_GENERAL:
925                                    rdp_process_general_caps(s);
926                                    break;
927    
928                            case RDP_CAPSET_BITMAP:
929                                    rdp_process_bitmap_caps(s);
930                                    break;
931                    }
932    
933                    s->p = next;
934            }
935    }
936    
937  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
938  static void  static void
939  process_demand_active(STREAM s)  process_demand_active(STREAM s)
940  {  {
941          uint8 type;          uint8 type;
942            uint16 len_src_descriptor, len_combined_caps;
943    
944          in_uint32_le(s, g_rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
945            in_uint16_le(s, len_src_descriptor);
946            in_uint16_le(s, len_combined_caps);
947            in_uint8s(s, len_src_descriptor);
948    
949          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
950            rdp_process_server_caps(s, len_combined_caps);
951    
952          rdp_send_confirm_active();          rdp_send_confirm_active();
953          rdp_send_synchronise();          rdp_send_synchronise();
# Line 607  process_demand_active(STREAM s) Line 957  process_demand_active(STREAM s)
957          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
958          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
959          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
960          rdp_send_fonts(1);  
961          rdp_send_fonts(2);          if (g_use_rdp5)
962          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */          {
963                    rdp_enum_bmpcache2();
964                    rdp_send_fonts(3);
965            }
966            else
967            {
968                    rdp_send_fonts(1);
969                    rdp_send_fonts(2);
970            }
971    
972            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
973          reset_order_state();          reset_order_state();
974  }  }
975    
# Line 730  process_bitmap_updates(STREAM s) Line 1090  process_bitmap_updates(STREAM s)
1090                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1091                         left, top, right, bottom, width, height, Bpp, compress));                         left, top, right, bottom, width, height, Bpp, compress));
1092    
                 /* Server may limit bpp - this is how we find out */  
                 if (g_server_bpp != bpp)  
                 {  
                         warning("Server limited colour depth to %d bits\n", bpp);  
                         g_server_bpp = bpp;  
                 }  
   
1093                  if (!compress)                  if (!compress)
1094                  {                  {
1095                          int y;                          int y;
# Line 816  process_update_pdu(STREAM s) Line 1169  process_update_pdu(STREAM s)
1169    
1170          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1171    
1172            ui_begin_update();
1173          switch (update_type)          switch (update_type)
1174          {          {
1175                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
# Line 839  process_update_pdu(STREAM s) Line 1193  process_update_pdu(STREAM s)
1193                  default:                  default:
1194                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1195          }          }
1196            ui_end_update();
1197    }
1198    
1199    /* Process a disconnect PDU */
1200    void
1201    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1202    {
1203            in_uint32_le(s, *ext_disc_reason);
1204    
1205            DEBUG(("Received disconnect PDU\n"));
1206  }  }
1207    
1208  /* Process data PDU */  /* Process data PDU */
1209  static void  static BOOL
1210  process_data_pdu(STREAM s)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1211  {  {
1212          uint8 data_pdu_type;          uint8 data_pdu_type;
1213            uint8 ctype;
1214            uint16 clen;
1215            uint32 len;
1216    
1217          in_uint8s(s, 8);        /* shareid, pad, streamid, length */          uint32 roff, rlen;
1218    
1219            struct stream *ns = &(g_mppc_dict.ns);
1220    
1221            in_uint8s(s, 6);        /* shareid, pad, streamid */
1222            in_uint16(s, len);
1223          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1224          in_uint8s(s, 3);        /* compress_type, compress_len */          in_uint8(s, ctype);
1225            in_uint16(s, clen);
1226            clen -= 18;
1227    
1228            if (ctype & RDP_MPPC_COMPRESSED)
1229            {
1230                    if (len > RDP_MPPC_DICT_SIZE)
1231                            error("error decompressed packet size exceeds max\n");
1232                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1233                            error("error while decompressing packet\n");
1234    
1235                    /* len -= 18; */
1236    
1237                    /* allocate memory and copy the uncompressed data into the temporary stream */
1238                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1239    
1240                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1241    
1242                    ns->size = rlen;
1243                    ns->end = (ns->data + ns->size);
1244                    ns->p = ns->data;
1245                    ns->rdp_hdr = ns->p;
1246    
1247                    s = ns;
1248            }
1249    
1250          switch (data_pdu_type)          switch (data_pdu_type)
1251          {          {
# Line 858  process_data_pdu(STREAM s) Line 1253  process_data_pdu(STREAM s)
1253                          process_update_pdu(s);                          process_update_pdu(s);
1254                          break;                          break;
1255    
1256                    case RDP_DATA_PDU_CONTROL:
1257                            DEBUG(("Received Control PDU\n"));
1258                            break;
1259    
1260                    case RDP_DATA_PDU_SYNCHRONISE:
1261                            DEBUG(("Received Sync PDU\n"));
1262                            break;
1263    
1264                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1265                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1266                          break;                          break;
# Line 872  process_data_pdu(STREAM s) Line 1275  process_data_pdu(STREAM s)
1275                          break;                          break;
1276    
1277                  case RDP_DATA_PDU_DISCONNECT:                  case RDP_DATA_PDU_DISCONNECT:
1278                          /* Normally received when user logs out or disconnects from a                          process_disconnect_pdu(s, ext_disc_reason);
1279                             console session on Windows XP and 2003 Server */                          return True;
                         DEBUG(("Received disconnect PDU\n"));  
                         break;  
1280    
1281                  default:                  default:
1282                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1283          }          }
1284            return False;
1285  }  }
1286    
1287  /* Process incoming packets */  /* Process incoming packets */
1288    /* nevers gets out of here till app is done */
1289    void
1290    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1291    {
1292            while (rdp_loop(deactivated, ext_disc_reason))
1293                    ;
1294    }
1295    
1296    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1297  BOOL  BOOL
1298  rdp_main_loop(void)  rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1299  {  {
1300          uint8 type;          uint8 type;
1301            BOOL disc = False;      /* True when a disconnect PDU was received */
1302            BOOL cont = True;
1303          STREAM s;          STREAM s;
1304    
1305          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1306          {          {
1307                    s = rdp_recv(&type);
1308                    if (s == NULL)
1309                            return False;
1310                  switch (type)                  switch (type)
1311                  {                  {
1312                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1313                                  process_demand_active(s);                                  process_demand_active(s);
1314                                    *deactivated = False;
1315                                  break;                                  break;
   
1316                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1317                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1318                                  /* We thought we could detect a clean                                  *deactivated = True;
                                    shutdown of the session by this  
                                    packet, but it seems Windows 2003  
                                    is sending us one of these when we  
                                    reconnect to a disconnected session  
                                    return True; */  
1319                                  break;                                  break;
   
1320                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1321                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1322                                  break;                                  break;
   
1323                          case 0:                          case 0:
1324                                  break;                                  break;
   
1325                          default:                          default:
1326                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1327                  }                  }
1328                    if (disc)
1329                            return False;
1330                    cont = g_next_packet < s->end;
1331          }          }
1332          return True;          return True;
         /* We want to detect if we got a clean shutdown, but we  
            can't. Se above.    
            return False;  */  
1333  }  }
1334    
1335  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */

Legend:
Removed from v.562  
changed lines
  Added in v.945

  ViewVC Help
Powered by ViewVC 1.1.26