/[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 658 by astrand, Fri Apr 16 11:36:29 2004 UTC revision 905 by jdmeijer, Fri May 20 22:09:32 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;  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 120  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          s->p += len;                  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  /* Input a string in Unicode
# Line 140  rdp_out_unistr(STREAM s, char *string, i Line 232  rdp_out_unistr(STREAM s, char *string, i
232  int  int
233  rdp_in_unistr(STREAM s, char *string, int uni_len)  rdp_in_unistr(STREAM s, char *string, int uni_len)
234  {  {
235          int i = 0;  #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          while (i < uni_len / 2)          if (g_iconv_works)
241          {          {
242                  in_uint8a(s, &string[i++], 1);                  if (iconv_h == (iconv_t) - 1)
243                  in_uint8s(s, 1);                  {
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          return i - 1;                  while (i < uni_len / 2)
271                    {
272                            in_uint8a(s, &string[i++], 1);
273                            in_uint8s(s, 1);
274                    }
275    
276                    return i - 1;
277            }
278  }  }
279    
280    
# Line 171  rdp_send_logon_info(uint32 flags, char * Line 297  rdp_send_logon_info(uint32 flags, char *
297          time_t t = time(NULL);          time_t t = time(NULL);
298          time_t tzone;          time_t tzone;
299    
 #if 0  
         // enable rdp compression  
         flags |= RDP_COMPRESSION;  
 #endif  
   
300          if (!g_use_rdp5 || 1 == g_server_rdp_version)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
301          {          {
302                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
# Line 198  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 359  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    
490            s = rdp_init_data(12);
491    
492            out_uint32_le(s, status);
493    
494            switch (status)
495            {
496                    case 0: /* shut the server up */
497                            break;
498    
499                    case 1: /* receive data again */
500                            out_uint32_le(s, 0);    /* unknown */
501                            out_uint16_le(s, g_width);
502                            out_uint16_le(s, g_height);
503                            break;
504            }
505    
506            s_mark_end(s);
507            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
508    }
509    
510    /* Send persistent bitmap cache enumeration PDU's */
511    static void
512    rdp_enum_bmpcache2(void)
513    {
514            STREAM s;
515            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
516            uint32 num_keys, offset, count, flags;
517    
518            offset = 0;
519            num_keys = pstcache_enumerate(2, keylist);
520    
521            while (offset < num_keys)
522            {
523                    count = MIN(num_keys - offset, 169);
524    
525                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
526    
527                    flags = 0;
528                    if (offset == 0)
529                            flags |= PDU_FLAG_FIRST;
530                    if (num_keys - offset <= 169)
531                            flags |= PDU_FLAG_LAST;
532    
533                    /* header */
534                    out_uint32_le(s, 0);
535                    out_uint16_le(s, count);
536                    out_uint16_le(s, 0);
537                    out_uint16_le(s, 0);
538                    out_uint16_le(s, 0);
539                    out_uint16_le(s, 0);
540                    out_uint16_le(s, num_keys);
541                    out_uint32_le(s, 0);
542                    out_uint32_le(s, flags);
543    
544                    /* list */
545                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
546    
547                    s_mark_end(s);
548                    rdp_send_data(s, 0x2b);
549    
550                    offset += 169;
551            }
552    }
553    
554  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
555  static void  static void
556  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 368  rdp_send_fonts(uint16 seq) Line 560  rdp_send_fonts(uint16 seq)
560          s = rdp_init_data(8);          s = rdp_init_data(8);
561    
562          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
563          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
564          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
565          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
566    
# Line 416  rdp_out_bitmap_caps(STREAM s) Line 608  rdp_out_bitmap_caps(STREAM s)
608          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
609          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
610          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
611          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
612          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
613          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
614          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
# Line 429  rdp_out_order_caps(STREAM s) Line 621  rdp_out_order_caps(STREAM s)
621  {  {
622          uint8 order_caps[32];          uint8 order_caps[32];
623    
   
624          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
625          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
626          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
627          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
628          order_caps[3] = 1;      /* required for memblt? */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
629            order_caps[4] = 0;      /* triblt */
630          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
631          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
632          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
633          order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
634          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
635          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
636            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
637            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
638          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
639            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
640            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
641          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
642          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
643          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 479  rdp_out_bmpcache_caps(STREAM s) Line 675  rdp_out_bmpcache_caps(STREAM s)
675          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
676  }  }
677    
678    /* Output bitmap cache v2 capability set */
679    static void
680    rdp_out_bmpcache2_caps(STREAM s)
681    {
682            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
683            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
684    
685            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
686    
687            out_uint16_be(s, 3);    /* number of caches in this set */
688    
689            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
690            out_uint32_le(s, BMPCACHE2_C0_CELLS);
691            out_uint32_le(s, BMPCACHE2_C1_CELLS);
692            if (pstcache_init(2))
693            {
694                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
695            }
696            else
697            {
698                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
699            }
700            out_uint8s(s, 20);      /* other bitmap caches not used */
701    }
702    
703  /* Output control capability set */  /* Output control capability set */
704  static void  static void
705  rdp_out_control_caps(STREAM s)  rdp_out_control_caps(STREAM s)
# Line 538  rdp_out_colcache_caps(STREAM s) Line 759  rdp_out_colcache_caps(STREAM s)
759          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
760  }  }
761    
762  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
763          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
764          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771          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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773          0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
774          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  };
775          0x10, 0x00, 0x34, 0x00, 0xFE,  
776          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
777          0xFE, 0x00, 0x08, 0x00, 0xFE,  
778          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
779          0xFE, 0x00, 0x80, 0x00, 0xFE,  
780          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  static uint8 caps_0x10[] = {
781          0x02, 0x00, 0x00, 0x00          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
782            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
783            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
784            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
785            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
786            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
787  };  };
788    
789  /* Output unknown capability sets (number 13, 12, 14 and 16) */  /* Output unknown capability sets */
790  static void  static void
791  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
792  {  {
793          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
794          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
795    
796          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
797  }  }
798    
799  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 581  rdp_send_confirm_active(void) Line 807  rdp_send_confirm_active(void)
807                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
808                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
809                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
810                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
811                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
812                    4 /* w2k fix, why? */ ;
813    
814          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
815    
# Line 601  rdp_send_confirm_active(void) Line 829  rdp_send_confirm_active(void)
829          rdp_out_general_caps(s);          rdp_out_general_caps(s);
830          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
831          rdp_out_order_caps(s);          rdp_out_order_caps(s);
832          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
833          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
834          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
835          rdp_out_control_caps(s);          rdp_out_control_caps(s);
836          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
837          rdp_out_share_caps(s);          rdp_out_share_caps(s);
838          rdp_out_unknown_caps(s);  
839            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
840            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
841            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
842            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
843    
844          s_mark_end(s);          s_mark_end(s);
845          sec_send(s, sec_flags);          sec_send(s, sec_flags);
846  }  }
847    
848  /* Respond to a demand active PDU */  /* Process a general capability set */
849  static void  static void
850  process_demand_active(STREAM s)  rdp_process_general_caps(STREAM s)
851  {  {
852          uint8 type;          uint16 pad2octetsB;     /* rdp5 flags? */
         uint16 i;  
         uint16 p_bpp;  
853    
854          in_uint32_le(s, g_rdp_shareid);          in_uint8s(s, 10);
855            in_uint16_le(s, pad2octetsB);
856    
857            if (!pad2octetsB)
858                    g_use_rdp5 = False;
859    }
860    
861    /* Process a bitmap capability set */
862    static void
863    rdp_process_bitmap_caps(STREAM s)
864    {
865            uint16 width, height, bpp;
866    
867            in_uint16_le(s, bpp);
868            in_uint8s(s, 6);
869    
870            in_uint16_le(s, width);
871            in_uint16_le(s, height);
872    
873            DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
874    
875            /*
876             * The server may limit bpp and change the size of the desktop (for
877             * example when shadowing another session).
878             */
879            if (g_server_bpp != bpp)
880            {
881                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
882                    g_server_bpp = bpp;
883            }
884            if (g_width != width || g_height != height)
885            {
886                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
887                            width, height);
888                    g_width = width;
889                    g_height = height;
890                    ui_resize_window();
891            }
892    }
893    
894    /* Process server capabilities */
895    void
896    rdp_process_server_caps(STREAM s, uint16 length)
897    {
898            int n;
899            uint8 *next, *start;
900            uint16 ncapsets, capset_type, capset_length;
901    
902            start = s->p;
903    
904          /* scan for prefered bpp */          in_uint16_le(s, ncapsets);
905          while (s_check_rem(s, 6))          in_uint8s(s, 2);        /* pad */
906    
907            for (n = 0; n < ncapsets; n++)
908          {          {
909                  in_uint16_le(s, i);                  if (s->p > start + length)
910                  if (i == RDP_CAPSET_BITMAP)                          return;
911    
912                    in_uint16_le(s, capset_type);
913                    in_uint16_le(s, capset_length);
914    
915                    next = s->p + capset_length - 4;
916    
917                    switch (capset_type)
918                  {                  {
919                          in_uint16_le(s, i);                          case RDP_CAPSET_GENERAL:
920                          if (i == RDP_CAPLEN_BITMAP)                                  rdp_process_general_caps(s);
921                          {                                  break;
922                                  in_uint16_le(s, p_bpp);  
923                                  if (p_bpp == 8 || p_bpp == 15 || p_bpp == 16 || p_bpp == 24)                          case RDP_CAPSET_BITMAP:
924                                  {                                  rdp_process_bitmap_caps(s);
925                                          if (p_bpp < g_server_bpp)                                  break;
                                         {  
                                                 warning("Server limited colour depth to %d bits\n",  
                                                         p_bpp);  
                                                 g_server_bpp = p_bpp;  
                                         }  
                                         break;  
                                 }  
                         }  
926                  }                  }
927    
928                    s->p = next;
929          }          }
930    }
931    
932    /* Respond to a demand active PDU */
933    static void
934    process_demand_active(STREAM s)
935    {
936            uint8 type;
937            uint16 len_src_descriptor, len_combined_caps;
938    
939            in_uint32_le(s, g_rdp_shareid);
940            in_uint16_le(s, len_src_descriptor);
941            in_uint16_le(s, len_combined_caps);
942            in_uint8s(s, len_src_descriptor);
943    
944          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
945            rdp_process_server_caps(s, len_combined_caps);
946    
947          rdp_send_confirm_active();          rdp_send_confirm_active();
948          rdp_send_synchronise();          rdp_send_synchronise();
# Line 658  process_demand_active(STREAM s) Line 952  process_demand_active(STREAM s)
952          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
953          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
954          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);
955          rdp_send_fonts(1);  
956          rdp_send_fonts(2);          if (g_use_rdp5)
957          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */          {
958                    rdp_enum_bmpcache2();
959                    rdp_send_fonts(3);
960            }
961            else
962            {
963                    rdp_send_fonts(1);
964                    rdp_send_fonts(2);
965            }
966    
967            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
968          reset_order_state();          reset_order_state();
969  }  }
970    
# Line 860  process_update_pdu(STREAM s) Line 1164  process_update_pdu(STREAM s)
1164    
1165          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1166    
1167            ui_begin_update();
1168          switch (update_type)          switch (update_type)
1169          {          {
1170                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
# Line 883  process_update_pdu(STREAM s) Line 1188  process_update_pdu(STREAM s)
1188                  default:                  default:
1189                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1190          }          }
1191            ui_end_update();
1192    }
1193    
1194    /* Process a disconnect PDU */
1195    void
1196    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1197    {
1198            in_uint32_le(s, *ext_disc_reason);
1199    
1200            DEBUG(("Received disconnect PDU\n"));
1201  }  }
1202    
1203  /* Process data PDU */  /* Process data PDU */
1204  static void  static BOOL
1205  process_data_pdu(STREAM s)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1206  {  {
1207          uint8 data_pdu_type;          uint8 data_pdu_type;
1208          uint8 ctype;          uint8 ctype;
1209          uint16 clen;          uint16 clen;
1210          int roff, rlen, len, ret;          uint32 len;
1211          static struct stream ns;  
1212          static signed char *dict = 0;          uint32 roff, rlen;
1213    
1214            struct stream *ns = &(g_mppc_dict.ns);
1215    
1216          in_uint8s(s, 6);        /* shareid, pad, streamid */          in_uint8s(s, 6);        /* shareid, pad, streamid */
1217          in_uint16(s, len);          in_uint16(s, len);
# Line 904  process_data_pdu(STREAM s) Line 1220  process_data_pdu(STREAM s)
1220          in_uint16(s, clen);          in_uint16(s, clen);
1221          clen -= 18;          clen -= 18;
1222    
1223  #if 0          if (ctype & RDP_MPPC_COMPRESSED)
         if (ctype & 0x20)  
1224          {          {
1225                  if (!dict)                  if (len > RDP_MPPC_DICT_SIZE)
1226                  {                          error("error decompressed packet size exceeds max\n");
1227                          dict = (signed char *) malloc(8200 * sizeof(signed char));                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1228                          dict = (signed char *) memset(dict, 0, 8200 * sizeof(signed char));                          error("error while decompressing packet\n");
                 }  
   
                 ret = decompress(s->p, clen, ctype, (signed char *) dict, &roff, &rlen);  
1229    
1230                  len -= 18;                  /* len -= 18; */
1231    
1232                  ns.data = xrealloc(ns.data, len);                  /* allocate memory and copy the uncompressed data into the temporary stream */
1233                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1234    
1235                  ns.data = (unsigned char *) memcpy(ns.data, (unsigned char *) (dict + roff), len);                  memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1236    
1237                  ns.size = len;                  ns->size = rlen;
1238                  ns.end = ns.data + ns.size;                  ns->end = (ns->data + ns->size);
1239                  ns.p = ns.data;                  ns->p = ns->data;
1240                  ns.rdp_hdr = ns.p;                  ns->rdp_hdr = ns->p;
1241    
1242                  s = &ns;                  s = ns;
1243          }          }
 #endif  
1244    
1245          switch (data_pdu_type)          switch (data_pdu_type)
1246          {          {
# Line 936  process_data_pdu(STREAM s) Line 1248  process_data_pdu(STREAM s)
1248                          process_update_pdu(s);                          process_update_pdu(s);
1249                          break;                          break;
1250    
1251                    case RDP_DATA_PDU_CONTROL:
1252                            DEBUG(("Received Control PDU\n"));
1253                            break;
1254    
1255                    case RDP_DATA_PDU_SYNCHRONISE:
1256                            DEBUG(("Received Sync PDU\n"));
1257                            break;
1258    
1259                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1260                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1261                          break;                          break;
# Line 950  process_data_pdu(STREAM s) Line 1270  process_data_pdu(STREAM s)
1270                          break;                          break;
1271    
1272                  case RDP_DATA_PDU_DISCONNECT:                  case RDP_DATA_PDU_DISCONNECT:
1273                          /* Normally received when user logs out or disconnects from a                          process_disconnect_pdu(s, ext_disc_reason);
1274                             console session on Windows XP and 2003 Server */                          return True;
                         DEBUG(("Received disconnect PDU\n"));  
                         break;  
1275    
1276                  default:                  default:
1277                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1278          }          }
1279            return False;
1280  }  }
1281    
1282  /* Process incoming packets */  /* Process incoming packets */
1283    /* nevers gets out of here till app is done */
1284    void
1285    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1286    {
1287            while (rdp_loop(deactivated, ext_disc_reason))
1288                    ;
1289    }
1290    
1291    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1292  BOOL  BOOL
1293  rdp_main_loop(void)  rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1294  {  {
1295          uint8 type;          uint8 type;
1296            BOOL disc = False;      /* True when a disconnect PDU was received */
1297            BOOL cont = True;
1298          STREAM s;          STREAM s;
1299    
1300          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1301          {          {
1302                    s = rdp_recv(&type);
1303                    if (s == NULL)
1304                            return False;
1305                  switch (type)                  switch (type)
1306                  {                  {
1307                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1308                                  process_demand_active(s);                                  process_demand_active(s);
1309                                    *deactivated = False;
1310                                  break;                                  break;
   
1311                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1312                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1313                                  /* 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; */  
1314                                  break;                                  break;
   
1315                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1316                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1317                                  break;                                  break;
   
1318                          case 0:                          case 0:
1319                                  break;                                  break;
   
1320                          default:                          default:
1321                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1322                  }                  }
1323                    if (disc)
1324                            return False;
1325                    cont = g_next_packet < s->end;
1326          }          }
1327          return True;          return True;
         /* We want to detect if we got a clean shutdown, but we  
            can't. Se above.    
            return False;  */  
1328  }  }
1329    
1330  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */

Legend:
Removed from v.658  
changed lines
  Added in v.905

  ViewVC Help
Powered by ViewVC 1.1.26