/[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

sourceforge.net/trunk/rdesktop/rdp.c revision 435 by astrand, Wed Jul 9 09:18:20 2003 UTC jpeg/rdesktop/trunk/rdp.c revision 1507 by dpavlin, Mon Jul 20 16:45:11 2009 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-2008
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    #ifndef _WIN32
23    #include <errno.h>
24    #include <unistd.h>
25    #endif
26  #include "rdesktop.h"  #include "rdesktop.h"
27    
28  extern uint16 g_mcs_userid;  #ifdef HAVE_ICONV
29  extern char username[16];  #ifdef HAVE_ICONV_H
30  extern BOOL bitmap_compression;  #include <iconv.h>
31  extern BOOL orders;  #endif
32  extern BOOL encryption;  
33  extern BOOL desktop_save;  #ifndef ICONV_CONST
34  extern BOOL use_rdp5;  #define ICONV_CONST ""
35  extern uint16 server_rdp_version;  #endif
36  extern int server_bpp;  #endif
37    
38  uint8 *next_packet;  extern uint16 g_mcs_userid;
39  uint32 rdp_shareid;  extern char *g_username;
40    extern char g_codepage[16];
41    extern RD_BOOL g_bitmap_compression;
42    extern RD_BOOL g_orders;
43    extern RD_BOOL g_encryption;
44    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;
48    extern uint32 g_rdp5_performanceflags;
49    extern int g_server_depth;
50    extern int g_width;
51    extern int g_height;
52    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;
57    uint32 g_rdp_shareid;
58    
59    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;
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 packetno;  static uint32 g_packetno;
73    #endif
74    
75    #ifdef HAVE_ICONV
76    static RD_BOOL g_iconv_works = True;
77  #endif  #endif
78    
79  /* Receive an RDP packet */  /* Receive an RDP packet */
# Line 43  rdp_recv(uint8 * type) Line 82  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) || (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                  next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
107          }          }
108          else          else
109          {          {
110                  rdp_s->p = next_packet;                  rdp_s->p = g_next_packet;
111          }          }
112    
113          in_uint16_le(rdp_s, length);          in_uint16_le(rdp_s, length);
114          /* 32k packets are really 8, keepalive fix */          /* 32k packets are really 8, keepalive fix */
115          if (length == 0x8000)          if (length == 0x8000)
116          {          {
117                  next_packet += 8;                  g_next_packet += 8;
118                  *type = 0;                  *type = 0;
119                  return rdp_s;                  return rdp_s;
120          }          }
# Line 70  rdp_recv(uint8 * type) Line 123  rdp_recv(uint8 * type)
123          *type = pdu_type & 0xf;          *type = pdu_type & 0xf;
124    
125  #if WITH_DEBUG  #if WITH_DEBUG
126          DEBUG(("RDP packet #%d, (type %x)\n", ++packetno, *type));          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
127          //      hexdump(next_packet, length);          hexdump(g_next_packet, length);
128  #endif /*  */  #endif /*  */
129    
130          next_packet += length;          g_next_packet += length;
131          return rdp_s;          return rdp_s;
132  }  }
133    
# Line 84  rdp_init_data(int maxlen) Line 137  rdp_init_data(int maxlen)
137  {  {
138          STREAM s;          STREAM s;
139    
140          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
141          s_push_layer(s, rdp_hdr, 18);          s_push_layer(s, rdp_hdr, 18);
142    
143          return s;          return s;
# Line 103  rdp_send_data(STREAM s, uint8 data_pdu_t Line 156  rdp_send_data(STREAM s, uint8 data_pdu_t
156          out_uint16_le(s, (RDP_PDU_DATA | 0x10));          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
157          out_uint16_le(s, (g_mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
158    
159          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
160          out_uint8(s, 0);        /* pad */          out_uint8(s, 0);        /* pad */
161          out_uint8(s, 1);        /* streamid */          out_uint8(s, 1);        /* streamid */
162          out_uint16_le(s, (length - 14));          out_uint16_le(s, (length - 14));
# Line 111  rdp_send_data(STREAM s, uint8 data_pdu_t Line 164  rdp_send_data(STREAM s, uint8 data_pdu_t
164          out_uint8(s, 0);        /* compress_type */          out_uint8(s, 0);        /* compress_type */
165          out_uint16(s, 0);       /* compress_len */          out_uint16(s, 0);       /* compress_len */
166    
167          sec_send(s, encryption ? SEC_ENCRYPT : 0);          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
168  }  }
169    
170  /* Output a string in Unicode */  /* Output a string in Unicode */
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                    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
242     *
243     * Returns str_len of string
244     */
245    int
246    rdp_in_unistr(STREAM s, char *string, int str_size, int in_len)
247    {
248    #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            if (g_iconv_works)
254            {
255                    if (iconv_h == (iconv_t) - 1)
256                    {
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          s->p += len;                  in_uint8s(s, rem);
311                    string[len] = 0;
312                    return len;
313            }
314  }  }
315    
316    
317  /* Parse a logon info packet */  /* Parse a logon info packet */
318  static void  static void
319  rdp_send_logon_info(uint32 flags, char *domain, char *user,  rdp_send_logon_info(uint32 flags, char *domain, char *user,
320                      char *password, char *program, char *directory)                      char *password, char *program, char *directory)
321  {  {
322            char *ipaddr = tcp_get_address();
323          int len_domain = 2 * strlen(domain);          int len_domain = 2 * strlen(domain);
324          int len_user = 2 * strlen(user);          int len_user = 2 * strlen(user);
325          int len_password = 2 * strlen(password);          int len_password = 2 * strlen(password);
326          int len_program = 2 * strlen(program);          int len_program = 2 * strlen(program);
327          int len_directory = 2 * strlen(directory);          int len_directory = 2 * strlen(directory);
328          int len_ip = 2 * strlen("127.0.0.1");          int len_ip = 2 * strlen(ipaddr);
329          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");          int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
330          int packetlen = 0;          int packetlen = 0;
331          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;
332          STREAM s;          STREAM s;
333            time_t t = time(NULL);
334            time_t tzone;
335    
336          if (!use_rdp5 || 1 == 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"));
339    
# Line 169  rdp_send_logon_info(uint32 flags, char * Line 355  rdp_send_logon_info(uint32 flags, char *
355          }          }
356          else          else
357          {          {
358    
359                  flags |= RDP_LOGON_BLOB;                  flags |= RDP_LOGON_BLOB;
360                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
361                  packetlen = 4 + // Unknown uint32                  packetlen = 4 + /* Unknown uint32 */
362                          4 +     // flags                          4 +     /* flags */
363                          2 +     // len_domain                          2 +     /* len_domain */
364                          2 +     // len_user                          2 +     /* len_user */
365                          (flags & RDP_LOGON_AUTO ? 2 : 0) +      // len_password                          (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
366                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      // Length of BLOB                          (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
367                          2 +     // len_program                          2 +     /* len_program */
368                          2 +     // len_directory                          2 +     /* len_directory */
369                          (0 < len_domain ? len_domain : 2) +     // domain                          (0 < len_domain ? len_domain : 2) +     /* domain */
370                          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? */
371                          (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. */
372                          (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) */
373                          2 +     // Client ip length                          2 +     /* Client ip length */
374                          len_ip +        // Client ip                          len_ip +        /* Client ip */
375                          2 +     // DLL string length                          2 +     /* DLL string length */
376                          len_dll +       // DLL string                          len_dll +       /* DLL string */
377                          2 +     // Unknown                          2 +     /* Unknown */
378                          2 +     // Unknown                          2 +     /* Unknown */
379                          64 +    // Time zone #0                          64 +    /* Time zone #0 */
380                          2 +     // Unknown                          2 +     /* Unknown */
381                          64 +    // Time zone #1                          64 +    /* Time zone #1 */
382                          32;     // Unknown                          32;     /* Unknown */
383    
384                  s = sec_init(sec_flags, packetlen);                  s = sec_init(sec_flags, packetlen);
385                  DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));                  DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
386    
387                  out_uint32(s, 0);       // Unknown                  out_uint32(s, 0);       /* Unknown */
388                  out_uint32_le(s, flags);                  out_uint32_le(s, flags);
389                  out_uint16_le(s, len_domain);                  out_uint16_le(s, len_domain);
390                  out_uint16_le(s, len_user);                  out_uint16_le(s, len_user);
# Line 243  rdp_send_logon_info(uint32 flags, char * Line 430  rdp_send_logon_info(uint32 flags, char *
430                          out_uint16_le(s, 0);                          out_uint16_le(s, 0);
431                  }                  }
432                  out_uint16_le(s, 2);                  out_uint16_le(s, 2);
433                  out_uint16_le(s, len_ip + 2);   // Length of client ip                  out_uint16_le(s, len_ip + 2);   /* Length of client ip */
434                  rdp_out_unistr(s, "127.0.0.1", len_ip);                  rdp_out_unistr(s, ipaddr, len_ip);
435                  out_uint16_le(s, len_dll + 2);                  out_uint16_le(s, len_dll + 2);
436                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);                  rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
437                  out_uint16_le(s, 0xffc4);  
438                  out_uint16_le(s, 0xffff);                  tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
439                    out_uint32_le(s, tzone);
440    
441                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));                  rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
442                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));                  out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
443    
   
444                  out_uint32_le(s, 0x0a0000);                  out_uint32_le(s, 0x0a0000);
445                  out_uint32_le(s, 0x050000);                  out_uint32_le(s, 0x050000);
446                  out_uint32_le(s, 3);                  out_uint32_le(s, 3);
# Line 268  rdp_send_logon_info(uint32 flags, char * Line 456  rdp_send_logon_info(uint32 flags, char *
456                  out_uint32(s, 0);                  out_uint32(s, 0);
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, 0x0f);                  out_uint32_le(s, g_rdp5_performanceflags);
460                  out_uint32(s, 0);                  out_uint16(s, 0);
461    
462    
463          }          }
# Line 329  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 338  rdp_send_fonts(uint16 seq) Line 601  rdp_send_fonts(uint16 seq)
601          s = rdp_init_data(8);          s = rdp_init_data(8);
602    
603          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
604          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
605          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
606          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
607    
# Line 358  rdp_out_general_caps(STREAM s) Line 621  rdp_out_general_caps(STREAM s)
621          out_uint16_le(s, 0x200);        /* Protocol version */          out_uint16_le(s, 0x200);        /* Protocol version */
622          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
623          out_uint16(s, 0);       /* Compression types */          out_uint16(s, 0);       /* Compression types */
624          out_uint16_le(s, use_rdp5 ? 0x40d : 0);          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
625          /* Pad, according to T.128. 0x40d seems to          /* Pad, according to T.128. 0x40d seems to
626             trigger             trigger
627             the server to start sending RDP5 packets.             the server to start sending RDP5 packets.
# Line 379  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, 8);    /* 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 */
649          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
650          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
651          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
652          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
653          out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
654          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
655          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
656          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
# Line 399  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] = 1;      /* required for 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] = (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 426  rdp_out_order_caps(STREAM s) Line 693  rdp_out_order_caps(STREAM s)
693          out_uint8p(s, order_caps, 32);  /* Orders supported */          out_uint8p(s, order_caps, 32);  /* Orders supported */
694          out_uint16_le(s, 0x6a1);        /* Text capability flags */          out_uint16_le(s, 0x6a1);        /* Text capability flags */
695          out_uint8s(s, 6);       /* Pad */          out_uint8s(s, 6);       /* Pad */
696          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 */
697          out_uint32(s, 0);       /* Unknown */          out_uint32(s, 0);       /* Unknown */
698          out_uint32_le(s, 0x4e4);        /* Unknown */          out_uint32_le(s, 0x4e4);        /* Unknown */
699  }  }
# Line 439  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 = (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 449  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 508  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[] = {  /* Output brush cache capability set */
804          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,  static void
805          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,  rdp_out_brushcache_caps(STREAM s)
806          0x00, 0x00, 0x00, 0x00, 0x00,  {
807          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          out_uint16_le(s, RDP_CAPSET_BRUSHCACHE);
808          0x00, 0x00, 0x00, 0x00, 0x00,          out_uint16_le(s, RDP_CAPLEN_BRUSHCACHE);
809          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          out_uint32_le(s, 1);    /* cache type */
810          0x00, 0x00, 0x00, 0x00, 0x00,  }
811          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
812          0x00, 0x00, 0x00, 0x00, 0x00,  static uint8 caps_0x0d[] = {
813          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
814          0x0C, 0x00, 0x08, 0x00, 0x01,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
815          0x00, 0x00, 0x00, 0x0E, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816          0x10, 0x00, 0x34, 0x00, 0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
817          0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x08, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818          0xFE, 0x00, 0x08, 0x00, 0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819          0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, 0xFE, 0x00, 0x40, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820          0xFE, 0x00, 0x80, 0x00, 0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
821          0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822          0x02, 0x00, 0x00, 0x00          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823            0x00, 0x00, 0x00, 0x00
824  };  };
825    
826  /* Output unknown capability sets (number 13, 12, 14 and 16) */  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
827    
828    static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
829    
830    static uint8 caps_0x10[] = {
831            0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
832            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
833            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
834            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
835            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
836            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
837    };
838    
839    /* Output unknown capability sets */
840  static void  static void
841  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
842  {  {
843          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
844          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
845    
846          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
847  }  }
848    
849  #define RDP5_FLAG 0x0030  #define RDP5_FLAG 0x0030
# Line 546  static void Line 852  static void
852  rdp_send_confirm_active(void)  rdp_send_confirm_active(void)
853  {  {
854          STREAM s;          STREAM s;
855          uint32 sec_flags = encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
856          uint16 caplen =          uint16 caplen =
857                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
858                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
859                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
860                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
861                    RDP_CAPLEN_BRUSHCACHE + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
862                    4 /* w2k fix, why? */ ;
863    
864          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
865    
# Line 559  rdp_send_confirm_active(void) Line 867  rdp_send_confirm_active(void)
867          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */          out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
868          out_uint16_le(s, (g_mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
869    
870          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
871          out_uint16_le(s, 0x3ea);        /* userid */          out_uint16_le(s, 0x3ea);        /* userid */
872          out_uint16_le(s, sizeof(RDP_SOURCE));          out_uint16_le(s, sizeof(RDP_SOURCE));
873          out_uint16_le(s, caplen);          out_uint16_le(s, caplen);
# Line 571  rdp_send_confirm_active(void) Line 879  rdp_send_confirm_active(void)
879          rdp_out_general_caps(s);          rdp_out_general_caps(s);
880          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
881          rdp_out_order_caps(s);          rdp_out_order_caps(s);
882          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
883          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
884          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
885          rdp_out_control_caps(s);          rdp_out_control_caps(s);
886          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
887          rdp_out_share_caps(s);          rdp_out_share_caps(s);
888          rdp_out_unknown_caps(s);          rdp_out_brushcache_caps(s);
889    
890            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
891            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
892            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
893            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
894    
895          s_mark_end(s);          s_mark_end(s);
896          sec_send(s, sec_flags);          sec_send(s, sec_flags);
897  }  }
898    
899    /* Process a general capability set */
900    static void
901    rdp_process_general_caps(STREAM s)
902    {
903            uint16 pad2octetsB;     /* rdp5 flags? */
904    
905            in_uint8s(s, 10);
906            in_uint16_le(s, pad2octetsB);
907    
908            if (!pad2octetsB)
909                    g_use_rdp5 = False;
910    }
911    
912    /* Process a bitmap capability set */
913    static void
914    rdp_process_bitmap_caps(STREAM s)
915    {
916            uint16 width, height, depth;
917    
918            in_uint16_le(s, depth);
919            in_uint8s(s, 6);
920    
921            in_uint16_le(s, width);
922            in_uint16_le(s, height);
923    
924            DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
925    
926            /*
927             * The server may limit depth and change the size of the desktop (for
928             * example when shadowing another session).
929             */
930            if (g_server_depth != depth)
931            {
932                    warning("Remote desktop does not support colour depth %d; falling back to %d\n",
933                            g_server_depth, depth);
934                    g_server_depth = depth;
935            }
936            if (g_width != width || g_height != height)
937            {
938                    warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
939                            width, height);
940                    g_width = width;
941                    g_height = height;
942                    ui_resize_window();
943            }
944    }
945    
946    /* Process server capabilities */
947    static void
948    rdp_process_server_caps(STREAM s, uint16 length)
949    {
950            int n;
951            uint8 *next, *start;
952            uint16 ncapsets, capset_type, capset_length;
953    
954            start = s->p;
955    
956            in_uint16_le(s, ncapsets);
957            in_uint8s(s, 2);        /* pad */
958    
959            for (n = 0; n < ncapsets; n++)
960            {
961                    if (s->p > start + length)
962                            return;
963    
964                    in_uint16_le(s, capset_type);
965                    in_uint16_le(s, capset_length);
966    
967                    next = s->p + capset_length - 4;
968    
969                    switch (capset_type)
970                    {
971                            case RDP_CAPSET_GENERAL:
972                                    rdp_process_general_caps(s);
973                                    break;
974    
975                            case RDP_CAPSET_BITMAP:
976                                    rdp_process_bitmap_caps(s);
977                                    break;
978                    }
979    
980                    s->p = next;
981            }
982    }
983    
984  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
985  static void  static void
986  process_demand_active(STREAM s)  process_demand_active(STREAM s)
987  {  {
988          uint8 type;          uint8 type;
989            uint16 len_src_descriptor, len_combined_caps;
990    
991          in_uint32_le(s, rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
992            in_uint16_le(s, len_src_descriptor);
993            in_uint16_le(s, len_combined_caps);
994            in_uint8s(s, len_src_descriptor);
995    
996          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
997            rdp_process_server_caps(s, len_combined_caps);
998    
999          rdp_send_confirm_active();          rdp_send_confirm_active();
1000          rdp_send_synchronise();          rdp_send_synchronise();
# Line 600  process_demand_active(STREAM s) Line 1003  process_demand_active(STREAM s)
1003          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
1004          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
1005          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
1006          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
1007          rdp_send_fonts(1);                         g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
         rdp_send_fonts(2);  
         rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */  
         reset_order_state();  
 }  
1008    
1009  /* Process a null system pointer PDU */          if (g_use_rdp5)
1010  void          {
1011  process_null_system_pointer_pdu(STREAM s)                  rdp_enum_bmpcache2();
1012  {                  rdp_send_fonts(3);
1013          // FIXME: We should probably set another cursor here,          }
1014          // like the X window system base cursor or something.          else
1015          ui_set_cursor(cache_get_cursor(0));          {
1016                    rdp_send_fonts(1);
1017                    rdp_send_fonts(2);
1018            }
1019    
1020            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
1021            reset_order_state();
1022  }  }
1023    
1024  /* Process a colour pointer PDU */  /* Process a colour pointer PDU */
# Line 622  process_colour_pointer_pdu(STREAM s) Line 1027  process_colour_pointer_pdu(STREAM s)
1027  {  {
1028          uint16 x, y, width, height, cache_idx, masklen, datalen;          uint16 x, y, width, height, cache_idx, masklen, datalen;
1029          uint8 *mask, *data;          uint8 *mask, *data;
1030          HCURSOR cursor;          RD_HCURSOR cursor;
1031    
1032          in_uint16_le(s, cache_idx);          in_uint16_le(s, cache_idx);
1033          in_uint16_le(s, x);          in_uint16_le(s, x);
# Line 648  process_cached_pointer_pdu(STREAM s) Line 1053  process_cached_pointer_pdu(STREAM s)
1053          ui_set_cursor(cache_get_cursor(cache_idx));          ui_set_cursor(cache_get_cursor(cache_idx));
1054  }  }
1055    
1056    /* Process a system pointer PDU */
1057    void
1058    process_system_pointer_pdu(STREAM s)
1059    {
1060            uint16 system_pointer_type;
1061    
1062            in_uint16_le(s, system_pointer_type);
1063            switch (system_pointer_type)
1064            {
1065                    case RDP_NULL_POINTER:
1066                            ui_set_null_cursor();
1067                            break;
1068    
1069                    default:
1070                            unimpl("System pointer message 0x%x\n", system_pointer_type);
1071            }
1072    }
1073    
1074  /* Process a pointer PDU */  /* Process a pointer PDU */
1075  static void  static void
# Line 676  process_pointer_pdu(STREAM s) Line 1098  process_pointer_pdu(STREAM s)
1098                          process_cached_pointer_pdu(s);                          process_cached_pointer_pdu(s);
1099                          break;                          break;
1100    
1101                    case RDP_POINTER_SYSTEM:
1102                            process_system_pointer_pdu(s);
1103                            break;
1104    
1105                  default:                  default:
1106                          DEBUG(("Pointer message 0x%x\n", message_type));                          unimpl("Pointer message 0x%x\n", message_type);
1107          }          }
1108  }  }
1109    
# Line 758  process_palette(STREAM s) Line 1184  process_palette(STREAM s)
1184  {  {
1185          COLOURENTRY *entry;          COLOURENTRY *entry;
1186          COLOURMAP map;          COLOURMAP map;
1187          HCOLOURMAP hmap;          RD_HCOLOURMAP hmap;
1188          int i;          int i;
1189    
1190          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1191          in_uint16_le(s, map.ncolours);          in_uint16_le(s, map.ncolours);
1192          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1193    
1194          map.colours = (COLOURENTRY *) xmalloc(3 * map.ncolours);          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1195    
1196          DEBUG(("PALETTE(c=%d)\n", map.ncolours));          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1197    
# Line 791  process_update_pdu(STREAM s) Line 1217  process_update_pdu(STREAM s)
1217    
1218          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1219    
1220            ui_begin_update();
1221          switch (update_type)          switch (update_type)
1222          {          {
1223                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
# Line 814  process_update_pdu(STREAM s) Line 1241  process_update_pdu(STREAM s)
1241                  default:                  default:
1242                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1243          }          }
1244            ui_end_update();
1245    }
1246    
1247    /* Process a disconnect PDU */
1248    void
1249    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1250    {
1251            in_uint32_le(s, *ext_disc_reason);
1252    
1253            DEBUG(("Received disconnect PDU\n"));
1254  }  }
1255    
1256  /* Process data PDU */  /* Process data PDU */
1257  static void  static RD_BOOL
1258  process_data_pdu(STREAM s)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1259  {  {
1260          uint8 data_pdu_type;          uint8 data_pdu_type;
1261            uint8 ctype;
1262            uint16 clen;
1263            uint32 len;
1264    
1265            uint32 roff, rlen;
1266    
1267            struct stream *ns = &(g_mppc_dict.ns);
1268    
1269          in_uint8s(s, 8);        /* shareid, pad, streamid, length */          in_uint8s(s, 6);        /* shareid, pad, streamid */
1270            in_uint16_le(s, len);
1271          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1272          in_uint8s(s, 3);        /* compress_type, compress_len */          in_uint8(s, ctype);
1273            in_uint16_le(s, clen);
1274            clen -= 18;
1275    
1276            if (ctype & RDP_MPPC_COMPRESSED)
1277            {
1278                    if (len > RDP_MPPC_DICT_SIZE)
1279                            error("error decompressed packet size exceeds max\n");
1280                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1281                            error("error while decompressing packet\n");
1282    
1283                    /* len -= 18; */
1284    
1285                    /* allocate memory and copy the uncompressed data into the temporary stream */
1286                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1287    
1288                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1289    
1290                    ns->size = rlen;
1291                    ns->end = (ns->data + ns->size);
1292                    ns->p = ns->data;
1293                    ns->rdp_hdr = ns->p;
1294    
1295                    s = ns;
1296            }
1297    
1298          switch (data_pdu_type)          switch (data_pdu_type)
1299          {          {
# Line 833  process_data_pdu(STREAM s) Line 1301  process_data_pdu(STREAM s)
1301                          process_update_pdu(s);                          process_update_pdu(s);
1302                          break;                          break;
1303    
1304                    case RDP_DATA_PDU_CONTROL:
1305                            DEBUG(("Received Control PDU\n"));
1306                            break;
1307    
1308                    case RDP_DATA_PDU_SYNCHRONISE:
1309                            DEBUG(("Received Sync PDU\n"));
1310                            break;
1311    
1312                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1313                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1314                          break;                          break;
# Line 846  process_data_pdu(STREAM s) Line 1322  process_data_pdu(STREAM s)
1322                          /* User logged on */                          /* User logged on */
1323                          break;                          break;
1324    
1325                    case RDP_DATA_PDU_DISCONNECT:
1326                            process_disconnect_pdu(s, ext_disc_reason);
1327    
1328                            /* We used to return true and disconnect immediately here, but
1329                             * Windows Vista sends a disconnect PDU with reason 0 when
1330                             * reconnecting to a disconnected session, and MSTSC doesn't
1331                             * drop the connection.  I think we should just save the status.
1332                             */
1333                            break;
1334    
1335                  default:                  default:
1336                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1337          }          }
1338            return False;
1339    }
1340    
1341    /* Process redirect PDU from Session Directory */
1342    static RD_BOOL
1343    process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1344    {
1345            uint32 len;
1346    
1347            /* these 2 bytes are unknown, seem to be zeros */
1348            in_uint8s(s, 2);
1349    
1350            /* read connection flags */
1351            in_uint32_le(s, g_redirect_flags);
1352    
1353            /* read length of ip string */
1354            in_uint32_le(s, len);
1355    
1356            /* read ip string */
1357            rdp_in_unistr(s, g_redirect_server, sizeof(g_redirect_server), len);
1358    
1359            /* read length of cookie string */
1360            in_uint32_le(s, len);
1361    
1362            /* read cookie string (plain ASCII) */
1363            if (len > sizeof(g_redirect_cookie) - 1)
1364            {
1365                    uint32 rem = len - (sizeof(g_redirect_cookie) - 1);
1366                    len = sizeof(g_redirect_cookie) - 1;
1367    
1368                    warning("Unexpectedly large redirection cookie\n");
1369                    in_uint8a(s, g_redirect_cookie, len);
1370                    in_uint8s(s, rem);
1371            }
1372            else
1373            {
1374                    in_uint8a(s, g_redirect_cookie, len);
1375            }
1376            g_redirect_cookie[len] = 0;
1377    
1378            /* read length of username string */
1379            in_uint32_le(s, len);
1380    
1381            /* read username string */
1382            g_redirect_username = (char *) xmalloc(len + 1);
1383            rdp_in_unistr(s, g_redirect_username, strlen(g_redirect_username), len);
1384    
1385            /* read length of domain string */
1386            in_uint32_le(s, len);
1387    
1388            /* read domain string */
1389            rdp_in_unistr(s, g_redirect_domain, sizeof(g_redirect_domain), len);
1390    
1391            /* read length of password string */
1392            in_uint32_le(s, len);
1393    
1394            /* read password string */
1395            rdp_in_unistr(s, g_redirect_password, sizeof(g_redirect_password), len);
1396    
1397            g_redirect = True;
1398    
1399            return True;
1400  }  }
1401    
1402  /* Process incoming packets */  /* Process incoming packets */
1403  BOOL  /* nevers gets out of here till app is done */
1404  rdp_main_loop(void)  void
1405    rdp_main_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1406    {
1407            while (rdp_loop(deactivated, ext_disc_reason))
1408                    ;
1409    }
1410    
1411    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1412    RD_BOOL
1413    rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
1414  {  {
1415          uint8 type;          uint8 type;
1416            RD_BOOL disc = False;   /* True when a disconnect PDU was received */
1417            RD_BOOL cont = True;
1418          STREAM s;          STREAM s;
1419    
1420          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1421          {          {
1422                    s = rdp_recv(&type);
1423                    if (s == NULL)
1424                            return False;
1425                  switch (type)                  switch (type)
1426                  {                  {
1427                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1428                                  process_demand_active(s);                                  process_demand_active(s);
1429                                    *deactivated = False;
1430                                  break;                                  break;
   
1431                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1432                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1433                                  /* We thought we could detect a clean                                  *deactivated = True;
1434                                     shutdown of the session by this                                  break;
1435                                     packet, but it seems Windows 2003                          case RDP_PDU_REDIRECT:
1436                                     is sending us one of these when we                                  return process_redirect_pdu(s);
                                    reconnect to a disconnected session  
                                    return True; */  
1437                                  break;                                  break;
   
1438                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1439                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1440                                  break;                                  break;
   
1441                          case 0:                          case 0:
1442                                  break;                                  break;
   
1443                          default:                          default:
1444                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1445                  }                  }
1446                    if (disc)
1447                            return False;
1448                    cont = g_next_packet < s->end;
1449          }          }
1450          return True;          return True;
         /* We want to detect if we got a clean shutdown, but we  
            can't. Se above.    
            return False;  */  
1451  }  }
1452    
1453  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
1454  BOOL  RD_BOOL
1455  rdp_connect(char *server, uint32 flags, char *domain, char *password,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1456              char *command, char *directory)              char *command, char *directory)
1457  {  {
1458          if (!sec_connect(server, username))          if (!sec_connect(server, g_username))
1459                  return False;                  return False;
1460    
1461          rdp_send_logon_info(flags, domain, username, password, command, directory);          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1462          return True;          return True;
1463  }  }
1464    
1465    /* Establish a reconnection up to the RDP layer */
1466    RD_BOOL
1467    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1468                  char *command, char *directory, char *cookie)
1469    {
1470            if (!sec_reconnect(server))
1471                    return False;
1472    
1473            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1474            return True;
1475    }
1476    
1477    /* Called during redirection to reset the state to support redirection */
1478    void
1479    rdp_reset_state(void)
1480    {
1481            g_next_packet = NULL;   /* reset the packet information */
1482            g_rdp_shareid = 0;
1483            sec_reset_state();
1484    }
1485    
1486  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1487  void  void
1488  rdp_disconnect(void)  rdp_disconnect(void)

Legend:
Removed from v.435  
changed lines
  Added in v.1507

  ViewVC Help
Powered by ViewVC 1.1.26