/[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 436 by jsorg71, Mon Jul 28 18:13:30 2003 UTC revision 848 by jsorg71, Sun Mar 13 03:29:19 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 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21    #include <time.h>
22  #include "rdesktop.h"  #include "rdesktop.h"
23    
24  extern uint16 g_mcs_userid;  extern uint16 g_mcs_userid;
25  extern char username[16];  extern char g_username[16];
26  extern BOOL bitmap_compression;  extern BOOL g_bitmap_compression;
27  extern BOOL orders;  extern BOOL g_orders;
28  extern BOOL encryption;  extern BOOL g_encryption;
29  extern BOOL desktop_save;  extern BOOL g_desktop_save;
30  extern BOOL use_rdp5;  extern BOOL g_polygon_ellipse_orders;
31  extern uint16 server_rdp_version;  extern BOOL g_use_rdp5;
32  extern int server_bpp;  extern uint16 g_server_rdp_version;
33    extern uint32 g_rdp5_performanceflags;
34    extern int g_server_bpp;
35    extern int g_width;
36    extern int g_height;
37    extern BOOL g_bitmap_cache;
38    extern BOOL g_bitmap_cache_persist_enable;
39    
40  uint8 *next_packet;  uint8 *g_next_packet;
41  uint32 rdp_shareid;  uint32 g_rdp_shareid;
42    
43    extern RDPCOMP g_mppc_dict;
44    
45  #if WITH_DEBUG  #if WITH_DEBUG
46  static uint32 packetno;  static uint32 g_packetno;
47  #endif  #endif
48    
49  /* Receive an RDP packet */  /* Receive an RDP packet */
# Line 43  rdp_recv(uint8 * type) Line 52  rdp_recv(uint8 * type)
52  {  {
53          static STREAM rdp_s;          static STREAM rdp_s;
54          uint16 length, pdu_type;          uint16 length, pdu_type;
55            uint8 rdpver;
56    
57          if ((rdp_s == NULL) || (next_packet >= rdp_s->end))          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
58          {          {
59                  rdp_s = sec_recv();                  rdp_s = sec_recv(&rdpver);
60                  if (rdp_s == NULL)                  if (rdp_s == NULL)
61                          return NULL;                          return NULL;
62                    if (rdpver == 0xff)
63                    {
64                            g_next_packet = rdp_s->end;
65                            *type = 0;
66                            return rdp_s;
67                    }
68                    else if (rdpver != 3)
69                    {
70                            /* rdp5_process should move g_next_packet ok */
71                            rdp5_process(rdp_s);
72                            *type = 0;
73                            return rdp_s;
74                    }
75    
76                  next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
77          }          }
78          else          else
79          {          {
80                  rdp_s->p = next_packet;                  rdp_s->p = g_next_packet;
81          }          }
82    
83          in_uint16_le(rdp_s, length);          in_uint16_le(rdp_s, length);
84          /* 32k packets are really 8, keepalive fix */          /* 32k packets are really 8, keepalive fix */
85          if (length == 0x8000)          if (length == 0x8000)
86          {          {
87                  next_packet += 8;                  g_next_packet += 8;
88                  *type = 0;                  *type = 0;
89                  return rdp_s;                  return rdp_s;
90          }          }
# Line 70  rdp_recv(uint8 * type) Line 93  rdp_recv(uint8 * type)
93          *type = pdu_type & 0xf;          *type = pdu_type & 0xf;
94    
95  #if WITH_DEBUG  #if WITH_DEBUG
96          DEBUG(("RDP packet #%d, (type %x)\n", ++packetno, *type));          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
97          //      hexdump(next_packet, length);          hexdump(g_next_packet, length);
98  #endif /*  */  #endif /*  */
99    
100          next_packet += length;          g_next_packet += length;
101          return rdp_s;          return rdp_s;
102  }  }
103    
# Line 84  rdp_init_data(int maxlen) Line 107  rdp_init_data(int maxlen)
107  {  {
108          STREAM s;          STREAM s;
109    
110          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
111          s_push_layer(s, rdp_hdr, 18);          s_push_layer(s, rdp_hdr, 18);
112    
113          return s;          return s;
# Line 103  rdp_send_data(STREAM s, uint8 data_pdu_t Line 126  rdp_send_data(STREAM s, uint8 data_pdu_t
126          out_uint16_le(s, (RDP_PDU_DATA | 0x10));          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
127          out_uint16_le(s, (g_mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
128    
129          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
130          out_uint8(s, 0);        /* pad */          out_uint8(s, 0);        /* pad */
131          out_uint8(s, 1);        /* streamid */          out_uint8(s, 1);        /* streamid */
132          out_uint16_le(s, (length - 14));          out_uint16_le(s, (length - 14));
# Line 111  rdp_send_data(STREAM s, uint8 data_pdu_t Line 134  rdp_send_data(STREAM s, uint8 data_pdu_t
134          out_uint8(s, 0);        /* compress_type */          out_uint8(s, 0);        /* compress_type */
135          out_uint16(s, 0);       /* compress_len */          out_uint16(s, 0);       /* compress_len */
136    
137          sec_send(s, encryption ? SEC_ENCRYPT : 0);          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
138  }  }
139    
140  /* Output a string in Unicode */  /* Output a string in Unicode */
# Line 131  rdp_out_unistr(STREAM s, char *string, i Line 154  rdp_out_unistr(STREAM s, char *string, i
154          s->p += len;          s->p += len;
155  }  }
156    
157    /* Input a string in Unicode
158     *
159     * Returns str_len of string
160     */
161    int
162    rdp_in_unistr(STREAM s, char *string, int uni_len)
163    {
164            int i = 0;
165    
166            while (i < uni_len / 2)
167            {
168                    in_uint8a(s, &string[i++], 1);
169                    in_uint8s(s, 1);
170            }
171    
172            return i - 1;
173    }
174    
175    
176  /* Parse a logon info packet */  /* Parse a logon info packet */
177  static void  static void
178  rdp_send_logon_info(uint32 flags, char *domain, char *user,  rdp_send_logon_info(uint32 flags, char *domain, char *user,
179                      char *password, char *program, char *directory)                      char *password, char *program, char *directory)
180  {  {
181            char *ipaddr = tcp_get_address();
182          int len_domain = 2 * strlen(domain);          int len_domain = 2 * strlen(domain);
183          int len_user = 2 * strlen(user);          int len_user = 2 * strlen(user);
184          int len_password = 2 * strlen(password);          int len_password = 2 * strlen(password);
185          int len_program = 2 * strlen(program);          int len_program = 2 * strlen(program);
186          int len_directory = 2 * strlen(directory);          int len_directory = 2 * strlen(directory);
187          int len_ip = 2 * strlen("127.0.0.1");          int len_ip = 2 * strlen(ipaddr);
188          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
189          int packetlen = 0;          int packetlen = 0;
190          uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;          uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
191          STREAM s;          STREAM s;
192            time_t t = time(NULL);
193            time_t tzone;
194    
195    #if 0
196            /* enable rdp compression */
197            /* some problems still exist with rdp5 */
198            flags |= RDP_COMPRESSION;
199    #endif
200    
201          if (!use_rdp5 || 1 == server_rdp_version)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
202          {          {
203                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
204    
# Line 169  rdp_send_logon_info(uint32 flags, char * Line 220  rdp_send_logon_info(uint32 flags, char *
220          }          }
221          else          else
222          {          {
223    
224                  flags |= RDP_LOGON_BLOB;                  flags |= RDP_LOGON_BLOB;
225                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
226                  packetlen = 4 + // Unknown uint32                  packetlen = 4 + /* Unknown uint32 */
227                          4 +     // flags                          4 +     /* flags */
228                          2 +     // len_domain                          2 +     /* len_domain */
229                          2 +     // len_user                          2 +     /* len_user */
230                          (flags & RDP_LOGON_AUTO ? 2 : 0) +      // len_password                          (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
231                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      // Length of BLOB                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
232                          2 +     // len_program                          2 +     /* len_program */
233                          2 +     // len_directory                          2 +     /* len_directory */
234                          (0 < len_domain ? len_domain : 2) +     // domain                          (0 < len_domain ? len_domain : 2) +     /* domain */
235                          len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    // We have no 512 byte BLOB. Perhaps we must?                          len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
236                          (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + // After the BLOB is a unknown int16. If there is a BLOB, that is.                          (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
237                          (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     // Unknown (2)                          (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
238                          2 +     // Client ip length                          2 +     /* Client ip length */
239                          len_ip +        // Client ip                          len_ip +        /* Client ip */
240                          2 +     // DLL string length                          2 +     /* DLL string length */
241                          len_dll +       // DLL string                          len_dll +       /* DLL string */
242                          2 +     // Unknown                          2 +     /* Unknown */
243                          2 +     // Unknown                          2 +     /* Unknown */
244                          64 +    // Time zone #0                          64 +    /* Time zone #0 */
245                          2 +     // Unknown                          2 +     /* Unknown */
246                          64 +    // Time zone #1                          64 +    /* Time zone #1 */
247                          32;     // Unknown                          32;     /* Unknown */
248    
249                  s = sec_init(sec_flags, packetlen);                  s = sec_init(sec_flags, packetlen);
250                  DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));                  DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
251    
252                  out_uint32(s, 0);       // Unknown                  out_uint32(s, 0);       /* Unknown */
253                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
254                  out_uint16_le(s, len_domain);                  out_uint16_le(s, len_domain);
255                  out_uint16_le(s, len_user);                  out_uint16_le(s, len_user);
# Line 243  rdp_send_logon_info(uint32 flags, char * Line 295  rdp_send_logon_info(uint32 flags, char *
295                          out_uint16_le(s, 0);                          out_uint16_le(s, 0);
296                  }                  }
297                  out_uint16_le(s, 2);                  out_uint16_le(s, 2);
298                  out_uint16_le(s, len_ip + 2);   // Length of client ip                  out_uint16_le(s, len_ip + 2);   /* Length of client ip */
299                  rdp_out_unistr(s, "127.0.0.1", len_ip);                  rdp_out_unistr(s, ipaddr, len_ip);
300                  out_uint16_le(s, len_dll + 2);                  out_uint16_le(s, len_dll + 2);
301                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
302                  out_uint16_le(s, 0xffc4);  
303                  out_uint16_le(s, 0xffff);                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
304                    out_uint32_le(s, tzone);
305    
306                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
307                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
308    
   
309                  out_uint32_le(s, 0x0a0000);                  out_uint32_le(s, 0x0a0000);
310                  out_uint32_le(s, 0x050000);                  out_uint32_le(s, 0x050000);
311                  out_uint32_le(s, 3);                  out_uint32_le(s, 3);
# Line 268  rdp_send_logon_info(uint32 flags, char * Line 321  rdp_send_logon_info(uint32 flags, char *
321                  out_uint32(s, 0);                  out_uint32(s, 0);
322                  out_uint32_le(s, 0xffffffc4);                  out_uint32_le(s, 0xffffffc4);
323                  out_uint32_le(s, 0xfffffffe);                  out_uint32_le(s, 0xfffffffe);
324                  out_uint32_le(s, 0x0f);                  out_uint32_le(s, g_rdp5_performanceflags);
325                  out_uint32(s, 0);                  out_uint32(s, 0);
326    
327    
# Line 329  rdp_send_input(uint32 time, uint16 messa Line 382  rdp_send_input(uint32 time, uint16 messa
382          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
383  }  }
384    
385    /* Inform the server on the contents of the persistent bitmap cache */
386    static void
387    rdp_enum_bmpcache2(void)
388    {
389            STREAM s;
390            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
391            uint32 num_keys, offset, count, flags;
392    
393            offset = 0;
394            num_keys = pstcache_enumerate(2, keylist);
395    
396            while (offset < num_keys)
397            {
398                    count = MIN(num_keys - offset, 169);
399    
400                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
401    
402                    flags = 0;
403                    if (offset == 0)
404                            flags |= PDU_FLAG_FIRST;
405                    if (num_keys - offset <= 169)
406                            flags |= PDU_FLAG_LAST;
407    
408                    /* header */
409                    out_uint32_le(s, 0);
410                    out_uint16_le(s, count);
411                    out_uint16_le(s, 0);
412                    out_uint16_le(s, 0);
413                    out_uint16_le(s, 0);
414                    out_uint16_le(s, 0);
415                    out_uint16_le(s, num_keys);
416                    out_uint32_le(s, 0);
417                    out_uint32_le(s, flags);
418    
419                    /* list */
420                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
421    
422                    s_mark_end(s);
423                    rdp_send_data(s, 0x2b);
424    
425                    offset += 169;
426            }
427    }
428    
429  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
430  static void  static void
431  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 338  rdp_send_fonts(uint16 seq) Line 435  rdp_send_fonts(uint16 seq)
435          s = rdp_init_data(8);          s = rdp_init_data(8);
436    
437          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
438          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
439          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
440          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
441    
# Line 358  rdp_out_general_caps(STREAM s) Line 455  rdp_out_general_caps(STREAM s)
455          out_uint16_le(s, 0x200);        /* Protocol version */          out_uint16_le(s, 0x200);        /* Protocol version */
456          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
457          out_uint16(s, 0);       /* Compression types */          out_uint16(s, 0);       /* Compression types */
458          out_uint16_le(s, use_rdp5 ? 0x40d : 0);          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
459          /* Pad, according to T.128. 0x40d seems to          /* Pad, according to T.128. 0x40d seems to
460             trigger             trigger
461             the server to start sending RDP5 packets.             the server to start sending RDP5 packets.
# Line 379  rdp_out_bitmap_caps(STREAM s) Line 476  rdp_out_bitmap_caps(STREAM s)
476          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
477          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
478    
479          out_uint16_le(s, 8);    /* Preferred BPP */          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
480          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
481          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
482          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
483          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
484          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
485          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
486          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
487          out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
488          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
489          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
490          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
# Line 399  rdp_out_order_caps(STREAM s) Line 496  rdp_out_order_caps(STREAM s)
496  {  {
497          uint8 order_caps[32];          uint8 order_caps[32];
498    
   
499          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
500          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
501          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
502          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
503          order_caps[3] = 1;      /* required for memblt? */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
504            order_caps[4] = 0;      /* triblt */
505          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
506          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
507          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
508          order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
509          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
510          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
511            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
512            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
513          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
514            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
515            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
516          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
517          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
518          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 426  rdp_out_order_caps(STREAM s) Line 527  rdp_out_order_caps(STREAM s)
527          out_uint8p(s, order_caps, 32);  /* Orders supported */          out_uint8p(s, order_caps, 32);  /* Orders supported */
528          out_uint16_le(s, 0x6a1);        /* Text capability flags */          out_uint16_le(s, 0x6a1);        /* Text capability flags */
529          out_uint8s(s, 6);       /* Pad */          out_uint8s(s, 6);       /* Pad */
530          out_uint32_le(s, desktop_save == False ? 0 : 0x38400);  /* Desktop cache size */          out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
531          out_uint32(s, 0);       /* Unknown */          out_uint32(s, 0);       /* Unknown */
532          out_uint32_le(s, 0x4e4);        /* Unknown */          out_uint32_le(s, 0x4e4);        /* Unknown */
533  }  }
# Line 439  rdp_out_bmpcache_caps(STREAM s) Line 540  rdp_out_bmpcache_caps(STREAM s)
540          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
541          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
542    
543          Bpp = (server_bpp + 7) / 8;          Bpp = (g_server_bpp + 7) / 8;
544          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
545          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
546          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
# Line 449  rdp_out_bmpcache_caps(STREAM s) Line 550  rdp_out_bmpcache_caps(STREAM s)
550          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
551  }  }
552    
553    /* Output bitmap cache v2 capability set */
554    static void
555    rdp_out_bmpcache2_caps(STREAM s)
556    {
557            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
558            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
559    
560            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
561    
562            out_uint16_le(s, 0x0300);       /* flags? number of caches? */
563    
564            out_uint32_le(s, BMPCACHE2_C0_CELLS);
565            out_uint32_le(s, BMPCACHE2_C1_CELLS);
566            if (pstcache_init(2))
567            {
568                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
569            }
570            else
571            {
572                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
573            }
574            out_uint8s(s, 20);      /* other bitmap caches not used */
575    }
576    
577  /* Output control capability set */  /* Output control capability set */
578  static void  static void
579  rdp_out_control_caps(STREAM s)  rdp_out_control_caps(STREAM s)
# Line 508  rdp_out_colcache_caps(STREAM s) Line 633  rdp_out_colcache_caps(STREAM s)
633          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
634  }  }
635    
636  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
637          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
638          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647          0x0C, 0x00, 0x08, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00
         0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,  
         0x10, 0x00, 0x34, 0x00, 0xFE,  
         0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,  
         0xFE, 0x00, 0x08, 0x00, 0xFE,  
         0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,  
         0xFE, 0x00, 0x80, 0x00, 0xFE,  
         0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,  
         0x02, 0x00, 0x00, 0x00  
648  };  };
649    
650  /* Output unknown capability sets (number 13, 12, 14 and 16) */  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
651    
652    static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
653    
654    static uint8 caps_0x10[] = {
655            0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
656            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
657            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
658            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
659            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
660            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
661    };
662    
663    /* Output unknown capability sets */
664  static void  static void
665  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
666  {  {
667          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
668          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
669    
670          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
671  }  }
672    
673  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 546  static void Line 676  static void
676  rdp_send_confirm_active(void)  rdp_send_confirm_active(void)
677  {  {
678          STREAM s;          STREAM s;
679          uint32 sec_flags = encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
680          uint16 caplen =          uint16 caplen =
681                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
682                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
683                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
684                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
685                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
686                    4 /* w2k fix, why? */ ;
687    
688          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
689    
# Line 559  rdp_send_confirm_active(void) Line 691  rdp_send_confirm_active(void)
691          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
692          out_uint16_le(s, (g_mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
693    
694          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
695          out_uint16_le(s, 0x3ea);        /* userid */          out_uint16_le(s, 0x3ea);        /* userid */
696          out_uint16_le(s, sizeof(RDP_SOURCE));          out_uint16_le(s, sizeof(RDP_SOURCE));
697          out_uint16_le(s, caplen);          out_uint16_le(s, caplen);
# Line 571  rdp_send_confirm_active(void) Line 703  rdp_send_confirm_active(void)
703          rdp_out_general_caps(s);          rdp_out_general_caps(s);
704          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
705          rdp_out_order_caps(s);          rdp_out_order_caps(s);
706          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
707          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
708          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
709          rdp_out_control_caps(s);          rdp_out_control_caps(s);
710          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
711          rdp_out_share_caps(s);          rdp_out_share_caps(s);
712          rdp_out_unknown_caps(s);  
713            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
714            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
715            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
716            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
717    
718          s_mark_end(s);          s_mark_end(s);
719          sec_send(s, sec_flags);          sec_send(s, sec_flags);
720  }  }
721    
722    /* Process a general capability set */
723    static void
724    rdp_process_general_caps(STREAM s)
725    {
726            uint16 pad2octetsB;     /* rdp5 flags? */
727    
728            in_uint8s(s, 10);
729            in_uint16_le(s, pad2octetsB);
730    
731            if (!pad2octetsB)
732                    g_use_rdp5 = False;
733    }
734    
735    /* Process a bitmap capability set */
736    static void
737    rdp_process_bitmap_caps(STREAM s)
738    {
739            uint16 width, height, bpp;
740    
741            in_uint16_le(s, bpp);
742            in_uint8s(s, 6);
743    
744            in_uint16_le(s, width);
745            in_uint16_le(s, height);
746    
747            DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
748    
749            /*
750             * The server may limit bpp and change the size of the desktop (for
751             * example when shadowing another session).
752             */
753            if (g_server_bpp != bpp)
754            {
755                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
756                    g_server_bpp = bpp;
757            }
758            if (g_width != width || g_height != height)
759            {
760                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
761                            width, height);
762                    g_width = width;
763                    g_height = height;
764                    ui_resize_window();
765            }
766    }
767    
768    /* Process server capabilities */
769    void
770    rdp_process_server_caps(STREAM s, uint16 length)
771    {
772            int n;
773            uint8 *next, *start;
774            uint16 ncapsets, capset_type, capset_length;
775    
776            start = s->p;
777    
778            in_uint16_le(s, ncapsets);
779            in_uint8s(s, 2);        /* pad */
780    
781            for (n = 0; n < ncapsets; n++)
782            {
783                    if (s->p > start + length)
784                            return;
785    
786                    in_uint16_le(s, capset_type);
787                    in_uint16_le(s, capset_length);
788    
789                    next = s->p + capset_length - 4;
790    
791                    switch (capset_type)
792                    {
793                            case RDP_CAPSET_GENERAL:
794                                    rdp_process_general_caps(s);
795                                    break;
796    
797                            case RDP_CAPSET_BITMAP:
798                                    rdp_process_bitmap_caps(s);
799                                    break;
800                    }
801    
802                    s->p = next;
803            }
804    }
805    
806  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
807  static void  static void
808  process_demand_active(STREAM s)  process_demand_active(STREAM s)
809  {  {
810          uint8 type;          uint8 type;
811            uint16 len_src_descriptor, len_combined_caps;
812    
813          in_uint32_le(s, rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
814            in_uint16_le(s, len_src_descriptor);
815            in_uint16_le(s, len_combined_caps);
816            in_uint8s(s, len_src_descriptor);
817    
818          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
819            rdp_process_server_caps(s, len_combined_caps);
820    
821          rdp_send_confirm_active();          rdp_send_confirm_active();
822          rdp_send_synchronise();          rdp_send_synchronise();
# Line 600  process_demand_active(STREAM s) Line 825  process_demand_active(STREAM s)
825          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
826          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
827          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
828          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
         rdp_send_fonts(1);  
         rdp_send_fonts(2);  
         rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */  
         reset_order_state();  
 }  
829    
830  /* Process a null system pointer PDU */          if (g_use_rdp5)
831  void          {
832  process_null_system_pointer_pdu(STREAM s)                  rdp_enum_bmpcache2();
833  {                  rdp_send_fonts(3);
834          // FIXME: We should probably set another cursor here,          }
835          // like the X window system base cursor or something.          else
836          ui_set_cursor(cache_get_cursor(0));          {
837                    rdp_send_fonts(1);
838                    rdp_send_fonts(2);
839            }
840    
841            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
842            reset_order_state();
843  }  }
844    
845  /* Process a colour pointer PDU */  /* Process a colour pointer PDU */
# Line 648  process_cached_pointer_pdu(STREAM s) Line 874  process_cached_pointer_pdu(STREAM s)
874          ui_set_cursor(cache_get_cursor(cache_idx));          ui_set_cursor(cache_get_cursor(cache_idx));
875  }  }
876    
877    /* Process a system pointer PDU */
878    void
879    process_system_pointer_pdu(STREAM s)
880    {
881            uint16 system_pointer_type;
882    
883            in_uint16(s, system_pointer_type);
884            switch (system_pointer_type)
885            {
886                    case RDP_NULL_POINTER:
887                            ui_set_null_cursor();
888                            break;
889    
890                    default:
891                            unimpl("System pointer message 0x%x\n", system_pointer_type);
892            }
893    }
894    
895  /* Process a pointer PDU */  /* Process a pointer PDU */
896  static void  static void
# Line 676  process_pointer_pdu(STREAM s) Line 919  process_pointer_pdu(STREAM s)
919                          process_cached_pointer_pdu(s);                          process_cached_pointer_pdu(s);
920                          break;                          break;
921    
922                    case RDP_POINTER_SYSTEM:
923                            process_system_pointer_pdu(s);
924                            break;
925    
926                  default:                  default:
927                          DEBUG(("Pointer message 0x%x\n", message_type));                          unimpl("Pointer message 0x%x\n", message_type);
928          }          }
929  }  }
930    
# Line 791  process_update_pdu(STREAM s) Line 1038  process_update_pdu(STREAM s)
1038    
1039          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1040    
1041            ui_begin_update();
1042          switch (update_type)          switch (update_type)
1043          {          {
1044                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
# Line 814  process_update_pdu(STREAM s) Line 1062  process_update_pdu(STREAM s)
1062                  default:                  default:
1063                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1064          }          }
1065            ui_end_update();
1066    }
1067    
1068    /* Process a disconnect PDU */
1069    void
1070    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1071    {
1072            in_uint32_le(s, *ext_disc_reason);
1073    
1074            DEBUG(("Received disconnect PDU\n"));
1075  }  }
1076    
1077  /* Process data PDU */  /* Process data PDU */
1078  static void  static BOOL
1079  process_data_pdu(STREAM s)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1080  {  {
1081          uint8 data_pdu_type;          uint8 data_pdu_type;
1082            uint8 ctype;
1083            uint16 clen;
1084            uint32 len;
1085    
1086            uint32 roff, rlen;
1087    
1088          in_uint8s(s, 8);        /* shareid, pad, streamid, length */          struct stream *ns = &(g_mppc_dict.ns);
1089    
1090            in_uint8s(s, 6);        /* shareid, pad, streamid */
1091            in_uint16(s, len);
1092          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1093          in_uint8s(s, 3);        /* compress_type, compress_len */          in_uint8(s, ctype);
1094            in_uint16(s, clen);
1095            clen -= 18;
1096    
1097            if (ctype & RDP_MPPC_COMPRESSED)
1098            {
1099                    if (len > RDP_MPPC_DICT_SIZE)
1100                            error("error decompressed packet size exceeds max\n");
1101                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1102                            error("error while decompressing packet\n");
1103    
1104                    //len -= 18;
1105    
1106                    /* allocate memory and copy the uncompressed data into the temporary stream */
1107                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1108    
1109                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1110    
1111                    ns->size = rlen;
1112                    ns->end = (ns->data + ns->size);
1113                    ns->p = ns->data;
1114                    ns->rdp_hdr = ns->p;
1115    
1116                    s = ns;
1117            }
1118    
1119          switch (data_pdu_type)          switch (data_pdu_type)
1120          {          {
# Line 833  process_data_pdu(STREAM s) Line 1122  process_data_pdu(STREAM s)
1122                          process_update_pdu(s);                          process_update_pdu(s);
1123                          break;                          break;
1124    
1125                    case RDP_DATA_PDU_CONTROL:
1126                            DEBUG(("Received Control PDU\n"));
1127                            break;
1128    
1129                    case RDP_DATA_PDU_SYNCHRONISE:
1130                            DEBUG(("Received Sync PDU\n"));
1131                            break;
1132    
1133                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1134                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1135                          break;                          break;
# Line 846  process_data_pdu(STREAM s) Line 1143  process_data_pdu(STREAM s)
1143                          /* User logged on */                          /* User logged on */
1144                          break;                          break;
1145    
1146                    case RDP_DATA_PDU_DISCONNECT:
1147                            process_disconnect_pdu(s, ext_disc_reason);
1148                            return True;
1149    
1150                  default:                  default:
1151                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1152          }          }
1153            return False;
1154  }  }
1155    
1156  /* Process incoming packets */  /* Process incoming packets */
1157    /* nevers gets out of here till app is done */
1158    void
1159    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1160    {
1161            while (rdp_loop(deactivated, ext_disc_reason))
1162                    ;
1163    }
1164    
1165    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1166  BOOL  BOOL
1167  rdp_main_loop(void)  rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1168  {  {
1169          uint8 type;          uint8 type;
1170            BOOL disc = False;      /* True when a disconnect PDU was received */
1171            BOOL cont = True;
1172          STREAM s;          STREAM s;
1173    
1174          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1175          {          {
1176                    s = rdp_recv(&type);
1177                    if (s == NULL)
1178                            return False;
1179                  switch (type)                  switch (type)
1180                  {                  {
1181                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1182                                  process_demand_active(s);                                  process_demand_active(s);
1183                                    *deactivated = False;
1184                                  break;                                  break;
   
1185                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1186                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1187                                  /* 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; */  
1188                                  break;                                  break;
   
1189                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1190                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1191                                  break;                                  break;
   
1192                          case 0:                          case 0:
1193                                  break;                                  break;
   
1194                          default:                          default:
1195                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1196                  }                  }
1197                    if (disc)
1198                            return False;
1199                    cont = g_next_packet < s->end;
1200          }          }
1201          return True;          return True;
         /* We want to detect if we got a clean shutdown, but we  
            can't. Se above.    
            return False;  */  
1202  }  }
1203    
1204  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
# Line 898  BOOL Line 1206  BOOL
1206  rdp_connect(char *server, uint32 flags, char *domain, char *password,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1207              char *command, char *directory)              char *command, char *directory)
1208  {  {
1209          if (!sec_connect(server, username))          if (!sec_connect(server, g_username))
1210                  return False;                  return False;
1211    
1212          rdp_send_logon_info(flags, domain, username, password, command, directory);          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1213          return True;          return True;
1214  }  }
1215    

Legend:
Removed from v.436  
changed lines
  Added in v.848

  ViewVC Help
Powered by ViewVC 1.1.26