/[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 713 by jsorg71, Wed Jun 16 03:08:55 2004 UTC revision 1372 by jsorg71, Mon Jan 8 04:47:06 2007 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 145  rdp_out_unistr(STREAM s, char *string, i Line 245  rdp_out_unistr(STREAM s, char *string, i
245  int  int
246  rdp_in_unistr(STREAM s, char *string, int uni_len)  rdp_in_unistr(STREAM s, char *string, int uni_len)
247  {  {
248          int i = 0;  #ifdef HAVE_ICONV
249            size_t ibl = uni_len, obl = uni_len;
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, uni_len);
264                            }
265                    }
266    
267                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
268                    {
269                            iconv_close(iconv_h);
270                            iconv_h = (iconv_t) - 1;
271                            warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
272    
273                            g_iconv_works = False;
274                            return rdp_in_unistr(s, string, uni_len);
275                    }
276    
277                    /* we must update the location of the current STREAM for future reads of s->p */
278                    s->p += uni_len;
279    
280                    return pout - string;
281          }          }
282            else
283    #endif
284            {
285                    int i = 0;
286    
287                    while (i < uni_len / 2)
288                    {
289                            in_uint8a(s, &string[i++], 1);
290                            in_uint8s(s, 1);
291                    }
292    
293          return i - 1;                  return i - 1;
294            }
295  }  }
296    
297    
# Line 176  rdp_send_logon_info(uint32 flags, char * Line 314  rdp_send_logon_info(uint32 flags, char *
314          time_t t = time(NULL);          time_t t = time(NULL);
315          time_t tzone;          time_t tzone;
316    
 #if 0  
         /* enable rdp compression */  
         /* some problems still exist with rdp5 */  
         flags |= RDP_COMPRESSION;  
 #endif  
   
317          if (!g_use_rdp5 || 1 == g_server_rdp_version)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
318          {          {
319                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
# Line 366  rdp_send_input(uint32 time, uint16 messa Line 498  rdp_send_input(uint32 time, uint16 messa
498          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
499  }  }
500    
501    /* Send a client window information PDU */
502    void
503    rdp_send_client_window_status(int status)
504    {
505            STREAM s;
506            static int current_status = 1;
507    
508            if (current_status == status)
509                    return;
510    
511            s = rdp_init_data(12);
512    
513            out_uint32_le(s, status);
514    
515            switch (status)
516            {
517                    case 0: /* shut the server up */
518                            break;
519    
520                    case 1: /* receive data again */
521                            out_uint32_le(s, 0);    /* unknown */
522                            out_uint16_le(s, g_width);
523                            out_uint16_le(s, g_height);
524                            break;
525            }
526    
527            s_mark_end(s);
528            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
529            current_status = status;
530    }
531    
532    /* Send persistent bitmap cache enumeration PDU's */
533    static void
534    rdp_enum_bmpcache2(void)
535    {
536            STREAM s;
537            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
538            uint32 num_keys, offset, count, flags;
539    
540            offset = 0;
541            num_keys = pstcache_enumerate(2, keylist);
542    
543            while (offset < num_keys)
544            {
545                    count = MIN(num_keys - offset, 169);
546    
547                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
548    
549                    flags = 0;
550                    if (offset == 0)
551                            flags |= PDU_FLAG_FIRST;
552                    if (num_keys - offset <= 169)
553                            flags |= PDU_FLAG_LAST;
554    
555                    /* header */
556                    out_uint32_le(s, 0);
557                    out_uint16_le(s, count);
558                    out_uint16_le(s, 0);
559                    out_uint16_le(s, 0);
560                    out_uint16_le(s, 0);
561                    out_uint16_le(s, 0);
562                    out_uint16_le(s, num_keys);
563                    out_uint32_le(s, 0);
564                    out_uint32_le(s, flags);
565    
566                    /* list */
567                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
568    
569                    s_mark_end(s);
570                    rdp_send_data(s, 0x2b);
571    
572                    offset += 169;
573            }
574    }
575    
576  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
577  static void  static void
578  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 416  rdp_out_bitmap_caps(STREAM s) Line 623  rdp_out_bitmap_caps(STREAM s)
623          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
624          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
625    
626          out_uint16_le(s, g_server_bpp); /* Preferred BPP */          out_uint16_le(s, g_server_depth);       /* Preferred colour depth */
627          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
628          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
629          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 643  rdp_out_order_caps(STREAM s)
643  {  {
644          uint8 order_caps[32];          uint8 order_caps[32];
645    
   
646          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
647          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
648          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
649          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
650          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
651            order_caps[4] = 0;      /* triblt */
652          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
653          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
654          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
655          order_caps[11] = (g_desktop_save == False ? 0 : 1);     /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
656          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
657          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
658            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
659            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
660          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
661            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
662            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
663          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
664          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
665          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 476  rdp_out_bmpcache_caps(STREAM s) Line 687  rdp_out_bmpcache_caps(STREAM s)
687          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
688          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
689    
690          Bpp = (g_server_bpp + 7) / 8;          Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
691          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
692          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
693          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 697  rdp_out_bmpcache_caps(STREAM s)
697          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
698  }  }
699    
700    /* Output bitmap cache v2 capability set */
701    static void
702    rdp_out_bmpcache2_caps(STREAM s)
703    {
704            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
705            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
706    
707            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
708    
709            out_uint16_be(s, 3);    /* number of caches in this set */
710    
711            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
712            out_uint32_le(s, BMPCACHE2_C0_CELLS);
713            out_uint32_le(s, BMPCACHE2_C1_CELLS);
714            if (pstcache_init(2))
715            {
716                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
717            }
718            else
719            {
720                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
721            }
722            out_uint8s(s, 20);      /* other bitmap caches not used */
723    }
724    
725  /* Output control capability set */  /* Output control capability set */
726  static void  static void
727  rdp_out_control_caps(STREAM s)  rdp_out_control_caps(STREAM s)
# Line 545  rdp_out_colcache_caps(STREAM s) Line 781  rdp_out_colcache_caps(STREAM s)
781          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
782  }  }
783    
784  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
785          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
786          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
793          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
794          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
795          0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
796          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  };
797          0x10, 0x00, 0x34, 0x00, 0xFE,  
798          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
799          0xFE, 0x00, 0x08, 0x00, 0xFE,  
800          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
801          0xFE, 0x00, 0x80, 0x00, 0xFE,  
802          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  static uint8 caps_0x10[] = {
803          0x02, 0x00, 0x00, 0x00          0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
804            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
805            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
806            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
807            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
808            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
809  };  };
810    
811  /* Output unknown capability sets (number 13, 12, 14 and 16) */  /* Output unknown capability sets */
812  static void  static void
813  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
814  {  {
815          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
816          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
817    
818          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
819  }  }
820    
821  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 588  rdp_send_confirm_active(void) Line 829  rdp_send_confirm_active(void)
829                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
830                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
831                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
832                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
833                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
834                    4 /* w2k fix, why? */ ;
835    
836          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
837    
# Line 608  rdp_send_confirm_active(void) Line 851  rdp_send_confirm_active(void)
851          rdp_out_general_caps(s);          rdp_out_general_caps(s);
852          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
853          rdp_out_order_caps(s);          rdp_out_order_caps(s);
854          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
855          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
856          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
857          rdp_out_control_caps(s);          rdp_out_control_caps(s);
858          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
859          rdp_out_share_caps(s);          rdp_out_share_caps(s);
860          rdp_out_unknown_caps(s);  
861            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
862            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
863            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
864            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
865    
866          s_mark_end(s);          s_mark_end(s);
867          sec_send(s, sec_flags);          sec_send(s, sec_flags);
# Line 637  rdp_process_general_caps(STREAM s) Line 884  rdp_process_general_caps(STREAM s)
884  static void  static void
885  rdp_process_bitmap_caps(STREAM s)  rdp_process_bitmap_caps(STREAM s)
886  {  {
887          uint16 width, height, bpp;          uint16 width, height, depth;
888    
889          in_uint16_le(s, bpp);          in_uint16_le(s, depth);
890          in_uint8s(s, 6);          in_uint8s(s, 6);
891    
892          in_uint16_le(s, width);          in_uint16_le(s, width);
893          in_uint16_le(s, height);          in_uint16_le(s, height);
894    
895          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));
896    
897          /*          /*
898           * 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
899           * example when shadowing another session).           * example when shadowing another session).
900           */           */
901          if (g_server_bpp != bpp)          if (g_server_depth != depth)
902          {          {
903                  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",
904                  g_server_bpp = bpp;                          g_server_depth, depth);
905                    g_server_depth = depth;
906          }          }
907          if (g_width != width || g_height != height)          if (g_width != width || g_height != height)
908          {          {
909                  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,
910                                  width, height);                          width, height);
911                  g_width = width;                  g_width = width;
912                  g_height = height;                  g_height = height;
913                  ui_resize_window();                  ui_resize_window();
914          }          }
915  }  }
916    
917  /* Respond to a demand active PDU */  /* Process server capabilities */
918  static void  static void
919  process_demand_active(STREAM s)  rdp_process_server_caps(STREAM s, uint16 length)
920  {  {
921          int n;          int n;
922          uint8 type, *next;          uint8 *next, *start;
923          uint16 len_src_descriptor, len_combined_caps, num_capsets, capset_type, capset_length;          uint16 ncapsets, capset_type, capset_length;
924    
925          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);  
926    
927          in_uint16_le(s, num_capsets);          in_uint16_le(s, ncapsets);
928          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
929    
930          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++)  
931          {          {
932                    if (s->p > start + length)
933                            return;
934    
935                  in_uint16_le(s, capset_type);                  in_uint16_le(s, capset_type);
936                  in_uint16_le(s, capset_length);                  in_uint16_le(s, capset_length);
937    
# Line 704  process_demand_active(STREAM s) Line 950  process_demand_active(STREAM s)
950    
951                  s->p = next;                  s->p = next;
952          }          }
953    }
954    
955    /* Respond to a demand active PDU */
956    static void
957    process_demand_active(STREAM s)
958    {
959            uint8 type;
960            uint16 len_src_descriptor, len_combined_caps;
961    
962            in_uint32_le(s, g_rdp_shareid);
963            in_uint16_le(s, len_src_descriptor);
964            in_uint16_le(s, len_combined_caps);
965            in_uint8s(s, len_src_descriptor);
966    
967            DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
968            rdp_process_server_caps(s, len_combined_caps);
969    
970          rdp_send_confirm_active();          rdp_send_confirm_active();
971          rdp_send_synchronise();          rdp_send_synchronise();
# Line 712  process_demand_active(STREAM s) Line 974  process_demand_active(STREAM s)
974          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
975          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
976          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
977          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
978                           g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
979    
980          if (g_use_rdp5)          if (g_use_rdp5)
981          {          {
982                    rdp_enum_bmpcache2();
983                  rdp_send_fonts(3);                  rdp_send_fonts(3);
984          }          }
985          else          else
# Line 734  process_colour_pointer_pdu(STREAM s) Line 998  process_colour_pointer_pdu(STREAM s)
998  {  {
999          uint16 x, y, width, height, cache_idx, masklen, datalen;          uint16 x, y, width, height, cache_idx, masklen, datalen;
1000          uint8 *mask, *data;          uint8 *mask, *data;
1001          HCURSOR cursor;          RD_HCURSOR cursor;
1002    
1003          in_uint16_le(s, cache_idx);          in_uint16_le(s, cache_idx);
1004          in_uint16_le(s, x);          in_uint16_le(s, x);
# Line 891  process_palette(STREAM s) Line 1155  process_palette(STREAM s)
1155  {  {
1156          COLOURENTRY *entry;          COLOURENTRY *entry;
1157          COLOURMAP map;          COLOURMAP map;
1158          HCOLOURMAP hmap;          RD_HCOLOURMAP hmap;
1159          int i;          int i;
1160    
1161          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
# Line 961  process_disconnect_pdu(STREAM s, uint32 Line 1225  process_disconnect_pdu(STREAM s, uint32
1225  }  }
1226    
1227  /* Process data PDU */  /* Process data PDU */
1228  static BOOL  static RD_BOOL
1229  process_data_pdu(STREAM s, uint32 * ext_disc_reason)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1230  {  {
1231          uint8 data_pdu_type;          uint8 data_pdu_type;
# Line 982  process_data_pdu(STREAM s, uint32 * ext_ Line 1246  process_data_pdu(STREAM s, uint32 * ext_
1246    
1247          if (ctype & RDP_MPPC_COMPRESSED)          if (ctype & RDP_MPPC_COMPRESSED)
1248          {          {
1249                    if (len > RDP_MPPC_DICT_SIZE)
1250                            error("error decompressed packet size exceeds max\n");
1251                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1252                          error("error while decompressing packet\n");                          error("error while decompressing packet\n");
1253    
1254                  //len -= 18;                  /* len -= 18; */
1255    
1256                  /* allocate memory and copy the uncompressed data into the temporary stream */                  /* allocate memory and copy the uncompressed data into the temporary stream */
1257                  ns->data = (uint8 *) xrealloc(ns->data, rlen);                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
# Line 1030  process_data_pdu(STREAM s, uint32 * ext_ Line 1295  process_data_pdu(STREAM s, uint32 * ext_
1295    
1296                  case RDP_DATA_PDU_DISCONNECT:                  case RDP_DATA_PDU_DISCONNECT:
1297                          process_disconnect_pdu(s, ext_disc_reason);                          process_disconnect_pdu(s, ext_disc_reason);
1298                          return True;  
1299                            /* We used to return true and disconnect immediately here, but
1300                             * Windows Vista sends a disconnect PDU with reason 0 when
1301                             * reconnecting to a disconnected session, and MSTSC doesn't
1302                             * drop the connection.  I think we should just save the status.
1303                             */
1304                            break;
1305    
1306                  default:                  default:
1307                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
# Line 1038  process_data_pdu(STREAM s, uint32 * ext_ Line 1309  process_data_pdu(STREAM s, uint32 * ext_
1309          return False;          return False;
1310  }  }
1311    
1312  /* Process incoming packets */  /* Process redirect PDU from Session Directory */
1313  void  static RD_BOOL
1314  rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)  process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1315  {  {
1316          uint8 type;          uint32 len;
         BOOL disc = False;      /* True when a disconnect PDU was received */  
         STREAM s;  
1317    
1318          while ((s = rdp_recv(&type)) != NULL)          /* these 2 bytes are unknown, seem to be zeros */
1319          {          in_uint8s(s, 2);
                 switch (type)  
                 {  
                         case RDP_PDU_DEMAND_ACTIVE:  
                                 process_demand_active(s);  
                                 *deactivated = False;  
                                 break;  
1320    
1321                          case RDP_PDU_DEACTIVATE:          /* read connection flags */
1322                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));          in_uint32_le(s, g_redirect_flags);
                                 *deactivated = True;  
                                 break;  
1323    
1324                          case RDP_PDU_DATA:          /* read length of ip string */
1325                                  disc = process_data_pdu(s, ext_disc_reason);          in_uint32_le(s, len);
                                 break;  
1326    
1327                          case 0:          /* read ip string */
1328                                  break;          rdp_in_unistr(s, g_redirect_server, len);
1329    
1330                          default:          /* read length of cookie string */
1331                                  unimpl("PDU %d\n", type);          in_uint32_le(s, len);
                 }  
1332    
1333                  if (disc)          /* read cookie string (plain ASCII) */
1334                  {          in_uint8a(s, g_redirect_cookie, len);
1335                          return;          g_redirect_cookie[len] = 0;
1336                  }  
1337          }          /* read length of username string */
1338          return;          in_uint32_le(s, len);
1339    
1340            /* read username string */
1341            rdp_in_unistr(s, g_redirect_username, len);
1342    
1343            /* read length of domain string */
1344            in_uint32_le(s, len);
1345    
1346            /* read domain string */
1347            rdp_in_unistr(s, g_redirect_domain, len);
1348    
1349            /* read length of password string */
1350            in_uint32_le(s, len);
1351    
1352            /* read password string */
1353            rdp_in_unistr(s, g_redirect_password, len);
1354    
1355            g_redirect = True;
1356    
1357            return True;
1358  }  }
1359    
1360  /* used in uiports, processes the rdp packets waiting */  /* Process incoming packets */
1361  BOOL  /* nevers gets out of here till app is done */
1362  rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)  void
1363    rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1364    {
1365            while (rdp_loop(deactivated, ext_disc_reason))
1366                    ;
1367    }
1368    
1369    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1370    RD_BOOL
1371    rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1372  {  {
1373          uint8 type;          uint8 type;
1374          BOOL disc = False;      /* True when a disconnect PDU was received */          RD_BOOL disc = False;   /* True when a disconnect PDU was received */
1375          BOOL cont = True;          RD_BOOL cont = True;
1376          STREAM s;          STREAM s;
1377    
1378     while (cont)          while (cont)
1379          {          {
1380                  s = rdp_recv(&type);                  s = rdp_recv(&type);
1381                  if (s == NULL)                  if (s == NULL)
# Line 1103  rdp_loop(BOOL * deactivated, uint32 * ex Line 1390  rdp_loop(BOOL * deactivated, uint32 * ex
1390                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1391                                  *deactivated = True;                                  *deactivated = True;
1392                                  break;                                  break;
1393                            case RDP_PDU_REDIRECT:
1394                                    return process_redirect_pdu(s);
1395                                    break;
1396                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1397                                  disc = process_data_pdu(s, ext_disc_reason);                                  disc = process_data_pdu(s, ext_disc_reason);
1398                                  break;                                  break;
# Line 1119  rdp_loop(BOOL * deactivated, uint32 * ex Line 1409  rdp_loop(BOOL * deactivated, uint32 * ex
1409  }  }
1410    
1411  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
1412  BOOL  RD_BOOL
1413  rdp_connect(char *server, uint32 flags, char *domain, char *password,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1414              char *command, char *directory)              char *command, char *directory)
1415  {  {
# Line 1130  rdp_connect(char *server, uint32 flags, Line 1420  rdp_connect(char *server, uint32 flags,
1420          return True;          return True;
1421  }  }
1422    
1423    /* Establish a reconnection up to the RDP layer */
1424    RD_BOOL
1425    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1426                  char *command, char *directory, char *cookie)
1427    {
1428            if (!sec_reconnect(server))
1429                    return False;
1430    
1431            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1432            return True;
1433    }
1434    
1435    /* Called during redirection to reset the state to support redirection */
1436    void
1437    rdp_reset_state(void)
1438    {
1439            g_next_packet = NULL;   /* reset the packet information */
1440            g_rdp_shareid = 0;
1441            sec_reset_state();
1442    }
1443    
1444  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1445  void  void
1446  rdp_disconnect(void)  rdp_disconnect(void)

Legend:
Removed from v.713  
changed lines
  Added in v.1372

  ViewVC Help
Powered by ViewVC 1.1.26