/[rdesktop]/jpeg/rdesktop/trunk/rdp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/rdp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 711 by jsorg71, Tue Jun 15 22:45:12 2004 UTC revision 1429 by astrand, Thu Jan 24 08:06:02 2008 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-2007
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    #ifndef _WIN32
23    #include <errno.h>
24    #include <unistd.h>
25    #endif
26  #include "rdesktop.h"  #include "rdesktop.h"
27    
28    #ifdef HAVE_ICONV
29    #ifdef HAVE_ICONV_H
30    #include <iconv.h>
31    #endif
32    
33    #ifndef ICONV_CONST
34    #define ICONV_CONST ""
35    #endif
36    #endif
37    
38  extern uint16 g_mcs_userid;  extern uint16 g_mcs_userid;
39  extern char g_username[16];  extern char g_username[64];
40  extern BOOL g_bitmap_compression;  extern char g_codepage[16];
41  extern BOOL g_orders;  extern RD_BOOL g_bitmap_compression;
42  extern BOOL g_encryption;  extern RD_BOOL g_orders;
43  extern BOOL g_desktop_save;  extern RD_BOOL g_encryption;
44  extern BOOL g_use_rdp5;  extern RD_BOOL g_desktop_save;
45    extern RD_BOOL g_polygon_ellipse_orders;
46    extern RD_BOOL g_use_rdp5;
47  extern uint16 g_server_rdp_version;  extern uint16 g_server_rdp_version;
48  extern uint32 g_rdp5_performanceflags;  extern uint32 g_rdp5_performanceflags;
49  extern int g_server_bpp;  extern int g_server_depth;
50  extern int g_width;  extern int g_width;
51  extern int g_height;  extern int g_height;
52  extern BOOL g_bitmap_cache;  extern RD_BOOL g_bitmap_cache;
53    extern RD_BOOL g_bitmap_cache_persist_enable;
54    extern RD_BOOL g_numlock_sync;
55    
56  uint8 *g_next_packet;  uint8 *g_next_packet;
57  uint32 g_rdp_shareid;  uint32 g_rdp_shareid;
58    
59  extern RDPCOMP g_mppc_dict;  extern RDPCOMP g_mppc_dict;
60    
61    /* Session Directory support */
62    extern RD_BOOL g_redirect;
63    extern char g_redirect_server[64];
64    extern char g_redirect_domain[16];
65    extern char g_redirect_password[64];
66    extern char g_redirect_username[64];
67    extern char g_redirect_cookie[128];
68    extern uint32 g_redirect_flags;
69    /* END Session Directory support */
70    
71  #if WITH_DEBUG  #if WITH_DEBUG
72  static uint32 g_packetno;  static uint32 g_packetno;
73  #endif  #endif
74    
75    #ifdef HAVE_ICONV
76    static RD_BOOL g_iconv_works = True;
77    #endif
78    
79  /* Receive an RDP packet */  /* Receive an RDP packet */
80  static STREAM  static STREAM
81  rdp_recv(uint8 * type)  rdp_recv(uint8 * type)
82  {  {
83          static STREAM rdp_s;          static STREAM rdp_s;
84          uint16 length, pdu_type;          uint16 length, pdu_type;
85            uint8 rdpver;
86    
87          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
88          {          {
89                  rdp_s = sec_recv();                  rdp_s = sec_recv(&rdpver);
90                  if (rdp_s == NULL)                  if (rdp_s == NULL)
91                          return NULL;                          return NULL;
92                    if (rdpver == 0xff)
93                    {
94                            g_next_packet = rdp_s->end;
95                            *type = 0;
96                            return rdp_s;
97                    }
98                    else if (rdpver != 3)
99                    {
100                            /* rdp5_process should move g_next_packet ok */
101                            rdp5_process(rdp_s);
102                            *type = 0;
103                            return rdp_s;
104                    }
105    
106                  g_next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
107          }          }
# Line 125  rdp_send_data(STREAM s, uint8 data_pdu_t Line 171  rdp_send_data(STREAM s, uint8 data_pdu_t
171  void  void
172  rdp_out_unistr(STREAM s, char *string, int len)  rdp_out_unistr(STREAM s, char *string, int len)
173  {  {
174          int i = 0, j = 0;  #ifdef HAVE_ICONV
175            size_t ibl = strlen(string), obl = len + 2;
176            static iconv_t iconv_h = (iconv_t) - 1;
177            char *pin = string, *pout = (char *) s->p;
178    
179          len += 2;          memset(pout, 0, len + 4);
180    
181          while (i < len)          if (g_iconv_works)
182          {          {
183                  s->p[i++] = string[j++];                  if (iconv_h == (iconv_t) - 1)
184                  s->p[i++] = 0;                  {
185                            size_t i = 1, o = 4;
186                            if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
187                            {
188                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %p\n",
189                                            g_codepage, WINDOWS_CODEPAGE, iconv_h);
190    
191                                    g_iconv_works = False;
192                                    rdp_out_unistr(s, string, len);
193                                    return;
194                            }
195                            if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
196                                (size_t) - 1)
197                            {
198                                    iconv_close(iconv_h);
199                                    iconv_h = (iconv_t) - 1;
200                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
201    
202                                    g_iconv_works = False;
203                                    rdp_out_unistr(s, string, len);
204                                    return;
205                            }
206                            pin = string;
207                            pout = (char *) s->p;
208                    }
209    
210                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
211                    {
212                            iconv_close(iconv_h);
213                            iconv_h = (iconv_t) - 1;
214                            warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
215    
216                            g_iconv_works = False;
217                            rdp_out_unistr(s, string, len);
218                            return;
219                    }
220    
221                    s->p += len + 2;
222    
223          }          }
224            else
225    #endif
226            {
227                    int i = 0, j = 0;
228    
229          s->p += len;                  len += 2;
230    
231                    while (i < len)
232                    {
233                            s->p[i++] = string[j++];
234                            s->p[i++] = 0;
235                    }
236    
237                    s->p += len;
238            }
239  }  }
240    
241  /* Input a string in Unicode  /* Input a string in Unicode
# Line 143  rdp_out_unistr(STREAM s, char *string, i Line 243  rdp_out_unistr(STREAM s, char *string, i
243   * Returns str_len of string   * Returns str_len of string
244   */   */
245  int  int
246  rdp_in_unistr(STREAM s, char *string, int uni_len)  rdp_in_unistr(STREAM s, char *string, int str_size, int in_len)
247  {  {
248          int i = 0;  #ifdef HAVE_ICONV
249            size_t ibl = in_len, obl = str_size - 1;
250            char *pin = (char *) s->p, *pout = string;
251            static iconv_t iconv_h = (iconv_t) - 1;
252    
253          while (i < uni_len / 2)          if (g_iconv_works)
254          {          {
255                  in_uint8a(s, &string[i++], 1);                  if (iconv_h == (iconv_t) - 1)
256                  in_uint8s(s, 1);                  {
257                            if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
258                            {
259                                    warning("rdp_in_unistr: iconv_open[%s -> %s] fail %p\n",
260                                            WINDOWS_CODEPAGE, g_codepage, iconv_h);
261    
262                                    g_iconv_works = False;
263                                    return rdp_in_unistr(s, string, str_size, in_len);
264                            }
265                    }
266    
267                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
268                    {
269                            if (errno == E2BIG)
270                            {
271                                    warning("server sent an unexpectedly long string, truncating\n");
272                            }
273                            else
274                            {
275                                    iconv_close(iconv_h);
276                                    iconv_h = (iconv_t) - 1;
277                                    warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
278    
279                                    g_iconv_works = False;
280                                    return rdp_in_unistr(s, string, str_size, in_len);
281                            }
282                    }
283    
284                    /* we must update the location of the current STREAM for future reads of s->p */
285                    s->p += in_len;
286    
287                    *pout = 0;
288                    return pout - string;
289          }          }
290            else
291    #endif
292            {
293                    int i = 0;
294                    int len = in_len / 2;
295                    int rem = 0;
296    
297                    if (len > str_size - 1)
298                    {
299                            warning("server sent an unexpectedly long string, truncating\n");
300                            len = str_size - 1;
301                            rem = in_len - 2 * len;
302                    }
303    
304                    while (i < len)
305                    {
306                            in_uint8a(s, &string[i++], 1);
307                            in_uint8s(s, 1);
308                    }
309    
310          return i - 1;                  in_uint8s(s, rem);
311                    string[len] = 0;
312                    return len;
313            }
314  }  }
315    
316    
# Line 176  rdp_send_logon_info(uint32 flags, char * Line 333  rdp_send_logon_info(uint32 flags, char *
333          time_t t = time(NULL);          time_t t = time(NULL);
334          time_t tzone;          time_t tzone;
335    
 #if 0  
         /* enable rdp compression */  
         /* some problems still exist with rdp5 */  
         flags |= RDP_COMPRESSION;  
 #endif  
   
336          if (!g_use_rdp5 || 1 == g_server_rdp_version)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
337          {          {
338                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
# Line 306  rdp_send_logon_info(uint32 flags, char * Line 457  rdp_send_logon_info(uint32 flags, char *
457                  out_uint32_le(s, 0xffffffc4);                  out_uint32_le(s, 0xffffffc4);
458                  out_uint32_le(s, 0xfffffffe);                  out_uint32_le(s, 0xfffffffe);
459                  out_uint32_le(s, g_rdp5_performanceflags);                  out_uint32_le(s, g_rdp5_performanceflags);
460                  out_uint32(s, 0);                  out_uint16(s, 0);
461    
462    
463          }          }
# Line 366  rdp_send_input(uint32 time, uint16 messa Line 517  rdp_send_input(uint32 time, uint16 messa
517          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
518  }  }
519    
520    /* Send a client window information PDU */
521    void
522    rdp_send_client_window_status(int status)
523    {
524            STREAM s;
525            static int current_status = 1;
526    
527            if (current_status == status)
528                    return;
529    
530            s = rdp_init_data(12);
531    
532            out_uint32_le(s, status);
533    
534            switch (status)
535            {
536                    case 0: /* shut the server up */
537                            break;
538    
539                    case 1: /* receive data again */
540                            out_uint32_le(s, 0);    /* unknown */
541                            out_uint16_le(s, g_width);
542                            out_uint16_le(s, g_height);
543                            break;
544            }
545    
546            s_mark_end(s);
547            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
548            current_status = status;
549    }
550    
551    /* Send persistent bitmap cache enumeration PDU's */
552    static void
553    rdp_enum_bmpcache2(void)
554    {
555            STREAM s;
556            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
557            uint32 num_keys, offset, count, flags;
558    
559            offset = 0;
560            num_keys = pstcache_enumerate(2, keylist);
561    
562            while (offset < num_keys)
563            {
564                    count = MIN(num_keys - offset, 169);
565    
566                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
567    
568                    flags = 0;
569                    if (offset == 0)
570                            flags |= PDU_FLAG_FIRST;
571                    if (num_keys - offset <= 169)
572                            flags |= PDU_FLAG_LAST;
573    
574                    /* header */
575                    out_uint32_le(s, 0);
576                    out_uint16_le(s, count);
577                    out_uint16_le(s, 0);
578                    out_uint16_le(s, 0);
579                    out_uint16_le(s, 0);
580                    out_uint16_le(s, 0);
581                    out_uint16_le(s, num_keys);
582                    out_uint32_le(s, 0);
583                    out_uint32_le(s, flags);
584    
585                    /* list */
586                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
587    
588                    s_mark_end(s);
589                    rdp_send_data(s, 0x2b);
590    
591                    offset += 169;
592            }
593    }
594    
595  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
596  static void  static void
597  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 416  rdp_out_bitmap_caps(STREAM s) Line 642  rdp_out_bitmap_caps(STREAM s)
642          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
643          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
644    
645          out_uint16_le(s, g_server_bpp); /* Preferred BPP */          out_uint16_le(s, g_server_depth);       /* Preferred colour depth */
646          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
647          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
648          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
# Line 436  rdp_out_order_caps(STREAM s) Line 662  rdp_out_order_caps(STREAM s)
662  {  {
663          uint8 order_caps[32];          uint8 order_caps[32];
664    
   
665          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
666          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
667          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
668          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
669          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
670            order_caps[4] = 0;      /* triblt */
671          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
672          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
673          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
674          order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
675          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
676          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
677            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
678            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
679          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
680            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
681            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
682          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
683          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
684          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 476  rdp_out_bmpcache_caps(STREAM s) Line 706  rdp_out_bmpcache_caps(STREAM s)
706          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
707          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
708    
709          Bpp = (g_server_bpp + 7) / 8;          Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
710          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
711          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
712          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
# Line 486  rdp_out_bmpcache_caps(STREAM s) Line 716  rdp_out_bmpcache_caps(STREAM s)
716          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
717  }  }
718    
719    /* Output bitmap cache v2 capability set */
720    static void
721    rdp_out_bmpcache2_caps(STREAM s)
722    {
723            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
724            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
725    
726            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
727    
728            out_uint16_be(s, 3);    /* number of caches in this set */
729    
730            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
731            out_uint32_le(s, BMPCACHE2_C0_CELLS);
732            out_uint32_le(s, BMPCACHE2_C1_CELLS);
733            if (pstcache_init(2))
734            {
735                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
736            }
737            else
738            {
739                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
740            }
741            out_uint8s(s, 20);      /* other bitmap caches not used */
742    }
743    
744  /* Output control capability set */  /* Output control capability set */
745  static void  static void
746  rdp_out_control_caps(STREAM s)  rdp_out_control_caps(STREAM s)
# Line 545  rdp_out_colcache_caps(STREAM s) Line 800  rdp_out_colcache_caps(STREAM s)
800          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
801  }  }
802    
803  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
804          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
805          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
809          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
810          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
811          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
812          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
813          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814          0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
815          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  };
816          0x10, 0x00, 0x34, 0x00, 0xFE,  
817          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
818          0xFE, 0x00, 0x08, 0x00, 0xFE,  
819          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
820          0xFE, 0x00, 0x80, 0x00, 0xFE,  
821          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  static uint8 caps_0x10[] = {
822          0x02, 0x00, 0x00, 0x00          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
823            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
824            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
825            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
826            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
827            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
828  };  };
829    
830  /* Output unknown capability sets (number 13, 12, 14 and 16) */  /* Output unknown capability sets */
831  static void  static void
832  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
833  {  {
834          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
835          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
836    
837          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
838  }  }
839    
840  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 588  rdp_send_confirm_active(void) Line 848  rdp_send_confirm_active(void)
848                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
849                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
850                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
851                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
852                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
853                    4 /* w2k fix, why? */ ;
854    
855          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
856    
# Line 608  rdp_send_confirm_active(void) Line 870  rdp_send_confirm_active(void)
870          rdp_out_general_caps(s);          rdp_out_general_caps(s);
871          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
872          rdp_out_order_caps(s);          rdp_out_order_caps(s);
873          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
874          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
875          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
876          rdp_out_control_caps(s);          rdp_out_control_caps(s);
877          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
878          rdp_out_share_caps(s);          rdp_out_share_caps(s);
879          rdp_out_unknown_caps(s);  
880            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
881            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
882            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
883            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
884    
885          s_mark_end(s);          s_mark_end(s);
886          sec_send(s, sec_flags);          sec_send(s, sec_flags);
# Line 637  rdp_process_general_caps(STREAM s) Line 903  rdp_process_general_caps(STREAM s)
903  static void  static void
904  rdp_process_bitmap_caps(STREAM s)  rdp_process_bitmap_caps(STREAM s)
905  {  {
906          uint16 width, height, bpp;          uint16 width, height, depth;
907    
908          in_uint16_le(s, bpp);          in_uint16_le(s, depth);
909          in_uint8s(s, 6);          in_uint8s(s, 6);
910    
911          in_uint16_le(s, width);          in_uint16_le(s, width);
912          in_uint16_le(s, height);          in_uint16_le(s, height);
913    
914          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));          DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
915    
916          /*          /*
917           * The server may limit bpp and change the size of the desktop (for           * The server may limit depth and change the size of the desktop (for
918           * example when shadowing another session).           * example when shadowing another session).
919           */           */
920          if (g_server_bpp != bpp)          if (g_server_depth != depth)
921          {          {
922                  warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);                  warning("Remote desktop does not support colour depth %d; falling back to %d\n",
923                  g_server_bpp = bpp;                          g_server_depth, depth);
924                    g_server_depth = depth;
925          }          }
926          if (g_width != width || g_height != height)          if (g_width != width || g_height != height)
927          {          {
928                  warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,                  warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
929                                  width, height);                          width, height);
930                  g_width = width;                  g_width = width;
931                  g_height = height;                  g_height = height;
932                  ui_resize_window();                  ui_resize_window();
933          }          }
934  }  }
935    
936  /* Respond to a demand active PDU */  /* Process server capabilities */
937  static void  static void
938  process_demand_active(STREAM s)  rdp_process_server_caps(STREAM s, uint16 length)
939  {  {
940          int n;          int n;
941          uint8 type, *next;          uint8 *next, *start;
942          uint16 len_src_descriptor, len_combined_caps, num_capsets, capset_type, capset_length;          uint16 ncapsets, capset_type, capset_length;
943    
944          in_uint32_le(s, g_rdp_shareid);          start = s->p;
         in_uint16_le(s, len_src_descriptor);  
         in_uint16_le(s, len_combined_caps);  
         in_uint8s(s, len_src_descriptor);  
945    
946          in_uint16_le(s, num_capsets);          in_uint16_le(s, ncapsets);
947          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
948    
949          DEBUG(("DEMAND_ACTIVE(id=0x%x,num_caps=%d)\n", g_rdp_shareid, num_capsets));          for (n = 0; n < ncapsets; n++)
   
         for (n = 0; n < num_capsets; n++)  
950          {          {
951                    if (s->p > start + length)
952                            return;
953    
954                  in_uint16_le(s, capset_type);                  in_uint16_le(s, capset_type);
955                  in_uint16_le(s, capset_length);                  in_uint16_le(s, capset_length);
956    
# Line 704  process_demand_active(STREAM s) Line 969  process_demand_active(STREAM s)
969    
970                  s->p = next;                  s->p = next;
971          }          }
972    }
973    
974    /* Respond to a demand active PDU */
975    static void
976    process_demand_active(STREAM s)
977    {
978            uint8 type;
979            uint16 len_src_descriptor, len_combined_caps;
980    
981            in_uint32_le(s, g_rdp_shareid);
982            in_uint16_le(s, len_src_descriptor);
983            in_uint16_le(s, len_combined_caps);
984            in_uint8s(s, len_src_descriptor);
985    
986            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
987            rdp_process_server_caps(s, len_combined_caps);
988    
989          rdp_send_confirm_active();          rdp_send_confirm_active();
990          rdp_send_synchronise();          rdp_send_synchronise();
# Line 712  process_demand_active(STREAM s) Line 993  process_demand_active(STREAM s)
993          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
994          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
995          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
996          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
997                           g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
998    
999          if (g_use_rdp5)          if (g_use_rdp5)
1000          {          {
1001                    rdp_enum_bmpcache2();
1002                  rdp_send_fonts(3);                  rdp_send_fonts(3);
1003          }          }
1004          else          else
# Line 734  process_colour_pointer_pdu(STREAM s) Line 1017  process_colour_pointer_pdu(STREAM s)
1017  {  {
1018          uint16 x, y, width, height, cache_idx, masklen, datalen;          uint16 x, y, width, height, cache_idx, masklen, datalen;
1019          uint8 *mask, *data;          uint8 *mask, *data;
1020          HCURSOR cursor;          RD_HCURSOR cursor;
1021    
1022          in_uint16_le(s, cache_idx);          in_uint16_le(s, cache_idx);
1023          in_uint16_le(s, x);          in_uint16_le(s, x);
# Line 766  process_system_pointer_pdu(STREAM s) Line 1049  process_system_pointer_pdu(STREAM s)
1049  {  {
1050          uint16 system_pointer_type;          uint16 system_pointer_type;
1051    
1052          in_uint16(s, system_pointer_type);          in_uint16_le(s, system_pointer_type);
1053          switch (system_pointer_type)          switch (system_pointer_type)
1054          {          {
1055                  case RDP_NULL_POINTER:                  case RDP_NULL_POINTER:
# Line 891  process_palette(STREAM s) Line 1174  process_palette(STREAM s)
1174  {  {
1175          COLOURENTRY *entry;          COLOURENTRY *entry;
1176          COLOURMAP map;          COLOURMAP map;
1177          HCOLOURMAP hmap;          RD_HCOLOURMAP hmap;
1178          int i;          int i;
1179    
1180          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
# Line 924  process_update_pdu(STREAM s) Line 1207  process_update_pdu(STREAM s)
1207    
1208          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1209    
1210            ui_begin_update();
1211          switch (update_type)          switch (update_type)
1212          {          {
1213                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
# Line 947  process_update_pdu(STREAM s) Line 1231  process_update_pdu(STREAM s)
1231                  default:                  default:
1232                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1233          }          }
1234            ui_end_update();
1235  }  }
1236    
1237  /* Process a disconnect PDU */  /* Process a disconnect PDU */
# Line 960  process_disconnect_pdu(STREAM s, uint32 Line 1244  process_disconnect_pdu(STREAM s, uint32
1244  }  }
1245    
1246  /* Process data PDU */  /* Process data PDU */
1247  static BOOL  static RD_BOOL
1248  process_data_pdu(STREAM s, uint32 * ext_disc_reason)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1249  {  {
1250          uint8 data_pdu_type;          uint8 data_pdu_type;
# Line 973  process_data_pdu(STREAM s, uint32 * ext_ Line 1257  process_data_pdu(STREAM s, uint32 * ext_
1257          struct stream *ns = &(g_mppc_dict.ns);          struct stream *ns = &(g_mppc_dict.ns);
1258    
1259          in_uint8s(s, 6);        /* shareid, pad, streamid */          in_uint8s(s, 6);        /* shareid, pad, streamid */
1260          in_uint16(s, len);          in_uint16_le(s, len);
1261          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1262          in_uint8(s, ctype);          in_uint8(s, ctype);
1263          in_uint16(s, clen);          in_uint16_le(s, clen);
1264          clen -= 18;          clen -= 18;
1265    
1266          if (ctype & RDP_MPPC_COMPRESSED)          if (ctype & RDP_MPPC_COMPRESSED)
1267          {          {
1268                    if (len > RDP_MPPC_DICT_SIZE)
1269                            error("error decompressed packet size exceeds max\n");
1270                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1271                          error("error while decompressing packet\n");                          error("error while decompressing packet\n");
1272    
1273                  //len -= 18;                  /* len -= 18; */
1274    
1275                  /* allocate memory and copy the uncompressed data into the temporary stream */                  /* allocate memory and copy the uncompressed data into the temporary stream */
1276                  ns->data = (uint8 *) xrealloc(ns->data, rlen);                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
# Line 1029  process_data_pdu(STREAM s, uint32 * ext_ Line 1314  process_data_pdu(STREAM s, uint32 * ext_
1314    
1315                  case RDP_DATA_PDU_DISCONNECT:                  case RDP_DATA_PDU_DISCONNECT:
1316                          process_disconnect_pdu(s, ext_disc_reason);                          process_disconnect_pdu(s, ext_disc_reason);
1317                          return True;  
1318                            /* We used to return true and disconnect immediately here, but
1319                             * Windows Vista sends a disconnect PDU with reason 0 when
1320                             * reconnecting to a disconnected session, and MSTSC doesn't
1321                             * drop the connection.  I think we should just save the status.
1322                             */
1323                            break;
1324    
1325                  default:                  default:
1326                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
# Line 1037  process_data_pdu(STREAM s, uint32 * ext_ Line 1328  process_data_pdu(STREAM s, uint32 * ext_
1328          return False;          return False;
1329  }  }
1330    
1331    /* Process redirect PDU from Session Directory */
1332    static RD_BOOL
1333    process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1334    {
1335            uint32 len;
1336    
1337            /* these 2 bytes are unknown, seem to be zeros */
1338            in_uint8s(s, 2);
1339    
1340            /* read connection flags */
1341            in_uint32_le(s, g_redirect_flags);
1342    
1343            /* read length of ip string */
1344            in_uint32_le(s, len);
1345    
1346            /* read ip string */
1347            rdp_in_unistr(s, g_redirect_server, sizeof(g_redirect_server), len);
1348    
1349            /* read length of cookie string */
1350            in_uint32_le(s, len);
1351    
1352            /* read cookie string (plain ASCII) */
1353            if (len > sizeof(g_redirect_cookie) - 1)
1354            {
1355                    uint32 rem = len - (sizeof(g_redirect_cookie) - 1);
1356                    len = sizeof(g_redirect_cookie) - 1;
1357    
1358                    warning("Unexpectedly large redirection cookie\n");
1359                    in_uint8a(s, g_redirect_cookie, len);
1360                    in_uint8s(s, rem);
1361            }
1362            else
1363            {
1364                    in_uint8a(s, g_redirect_cookie, len);
1365            }
1366            g_redirect_cookie[len] = 0;
1367    
1368            /* read length of username string */
1369            in_uint32_le(s, len);
1370    
1371            /* read username string */
1372            rdp_in_unistr(s, g_redirect_username, sizeof(g_redirect_username), len);
1373    
1374            /* read length of domain string */
1375            in_uint32_le(s, len);
1376    
1377            /* read domain string */
1378            rdp_in_unistr(s, g_redirect_domain, sizeof(g_redirect_domain), len);
1379    
1380            /* read length of password string */
1381            in_uint32_le(s, len);
1382    
1383            /* read password string */
1384            rdp_in_unistr(s, g_redirect_password, sizeof(g_redirect_password), len);
1385    
1386            g_redirect = True;
1387    
1388            return True;
1389    }
1390    
1391  /* Process incoming packets */  /* Process incoming packets */
1392    /* nevers gets out of here till app is done */
1393  void  void
1394  rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)  rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1395    {
1396            while (rdp_loop(deactivated, ext_disc_reason))
1397                    ;
1398    }
1399    
1400    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1401    RD_BOOL
1402    rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1403  {  {
1404          uint8 type;          uint8 type;
1405          BOOL disc = False;      /* True when a disconnect PDU was received */          RD_BOOL disc = False;   /* True when a disconnect PDU was received */
1406            RD_BOOL cont = True;
1407          STREAM s;          STREAM s;
1408    
1409          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1410          {          {
1411                    s = rdp_recv(&type);
1412                    if (s == NULL)
1413                            return False;
1414                  switch (type)                  switch (type)
1415                  {                  {
1416                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1417                                  process_demand_active(s);                                  process_demand_active(s);
1418                                  *deactivated = False;                                  *deactivated = False;
1419                                  break;                                  break;
   
1420                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1421                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1422                                  *deactivated = True;                                  *deactivated = True;
1423                                  break;                                  break;
1424                            case RDP_PDU_REDIRECT:
1425                                    return process_redirect_pdu(s);
1426                                    break;
1427                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1428                                  disc = process_data_pdu(s, ext_disc_reason);                                  disc = process_data_pdu(s, ext_disc_reason);
1429                                  break;                                  break;
   
1430                          case 0:                          case 0:
1431                                  break;                                  break;
   
1432                          default:                          default:
1433                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1434                  }                  }
   
1435                  if (disc)                  if (disc)
1436                  {                          return False;
1437                          return;                  cont = g_next_packet < s->end;
                 }  
1438          }          }
1439          return;          return True;
1440  }  }
1441    
1442  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
1443  BOOL  RD_BOOL
1444  rdp_connect(char *server, uint32 flags, char *domain, char *password,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1445              char *command, char *directory)              char *command, char *directory)
1446  {  {
# Line 1090  rdp_connect(char *server, uint32 flags, Line 1451  rdp_connect(char *server, uint32 flags,
1451          return True;          return True;
1452  }  }
1453    
1454    /* Establish a reconnection up to the RDP layer */
1455    RD_BOOL
1456    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1457                  char *command, char *directory, char *cookie)
1458    {
1459            if (!sec_reconnect(server))
1460                    return False;
1461    
1462            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1463            return True;
1464    }
1465    
1466    /* Called during redirection to reset the state to support redirection */
1467    void
1468    rdp_reset_state(void)
1469    {
1470            g_next_packet = NULL;   /* reset the packet information */
1471            g_rdp_shareid = 0;
1472            sec_reset_state();
1473    }
1474    
1475  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1476  void  void
1477  rdp_disconnect(void)  rdp_disconnect(void)

Legend:
Removed from v.711  
changed lines
  Added in v.1429

  ViewVC Help
Powered by ViewVC 1.1.26