/[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 176 by n-ki, Tue Sep 17 09:55:03 2002 UTC revision 1042 by astrand, Tue Jan 24 12:40:24 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- 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-2001     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
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
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 <errno.h>
23    #include <unistd.h>
24  #include "rdesktop.h"  #include "rdesktop.h"
25    
26  extern uint16 mcs_userid;  #ifdef HAVE_ICONV
27  extern char username[16];  #ifdef HAVE_ICONV_H
28  extern BOOL bitmap_compression;  #include <iconv.h>
29  extern BOOL orders;  #endif
30  extern BOOL encryption;  
31  extern BOOL desktop_save;  #ifndef ICONV_CONST
32    #define ICONV_CONST ""
33  uint8 *next_packet;  #endif
34  uint32 rdp_shareid;  #endif
35    
36  /* Initialise an RDP packet */  extern uint16 g_mcs_userid;
37  static STREAM  extern char g_username[64];
38  rdp_init(int maxlen)  extern char g_codepage[16];
39  {  extern BOOL g_bitmap_compression;
40          STREAM s;  extern BOOL g_orders;
41    extern BOOL g_encryption;
42          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 6);  extern BOOL g_desktop_save;
43          s_push_layer(s, rdp_hdr, 6);  extern BOOL g_polygon_ellipse_orders;
44    extern BOOL g_use_rdp5;
45          return s;  extern uint16 g_server_rdp_version;
46  }  extern uint32 g_rdp5_performanceflags;
47    extern int g_server_depth;
48  /* Send an RDP packet */  extern int g_width;
49  static void  extern int g_height;
50  rdp_send(STREAM s, uint8 pdu_type)  extern BOOL g_bitmap_cache;
51  {  extern BOOL g_bitmap_cache_persist_enable;
52          uint16 length;  
53    uint8 *g_next_packet;
54          s_pop_layer(s, rdp_hdr);  uint32 g_rdp_shareid;
55          length = s->end - s->p;  
56    extern RDPCOMP g_mppc_dict;
57    
58    /* Session Directory support */
59    extern BOOL g_redirect;
60    extern char g_redirect_server[64];
61    extern char g_redirect_domain[16];
62    extern char g_redirect_password[64];
63    extern char g_redirect_username[64];
64    extern char g_redirect_cookie[128];
65    extern uint32 g_redirect_flags;
66    /* END Session Directory support */
67    
68          out_uint16_le(s, length);  #if WITH_DEBUG
69          out_uint16_le(s, (pdu_type | 0x10));    /* Version 1 */  static uint32 g_packetno;
70          out_uint16_le(s, (mcs_userid + 1001));  #endif
71    
72          sec_send(s, encryption ? SEC_ENCRYPT : 0);  #ifdef HAVE_ICONV
73  }  static BOOL g_iconv_works = True;
74    #endif
75    
76  /* Receive an RDP packet */  /* Receive an RDP packet */
77  static STREAM  static STREAM
# Line 64  rdp_recv(uint8 * type) Line 79  rdp_recv(uint8 * type)
79  {  {
80          static STREAM rdp_s;          static STREAM rdp_s;
81          uint16 length, pdu_type;          uint16 length, pdu_type;
82            uint8 rdpver;
83    
84          if ((rdp_s == NULL) || (next_packet >= rdp_s->end))          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
85          {          {
86                  rdp_s = sec_recv();                  rdp_s = sec_recv(&rdpver);
87                  if (rdp_s == NULL)                  if (rdp_s == NULL)
88                          return NULL;                          return NULL;
89                    if (rdpver == 0xff)
90                    {
91                            g_next_packet = rdp_s->end;
92                            *type = 0;
93                            return rdp_s;
94                    }
95                    else if (rdpver != 3)
96                    {
97                            /* rdp5_process should move g_next_packet ok */
98                            rdp5_process(rdp_s);
99                            *type = 0;
100                            return rdp_s;
101                    }
102    
103                  next_packet = rdp_s->p;                  g_next_packet = rdp_s->p;
104          }          }
105          else          else
106          {          {
107                  rdp_s->p = next_packet;                  rdp_s->p = g_next_packet;
108          }          }
109    
110          in_uint16_le(rdp_s, length);          in_uint16_le(rdp_s, length);
111            /* 32k packets are really 8, keepalive fix */
112            if (length == 0x8000)
113            {
114                    g_next_packet += 8;
115                    *type = 0;
116                    return rdp_s;
117            }
118          in_uint16_le(rdp_s, pdu_type);          in_uint16_le(rdp_s, pdu_type);
119          in_uint8s(rdp_s, 2);    /* userid */          in_uint8s(rdp_s, 2);    /* userid */
120          *type = pdu_type & 0xf;          *type = pdu_type & 0xf;
121    
122  #if WITH_DEBUG  #if WITH_DEBUG
123          DEBUG(("RDP packet (type %x):\n", *type));          DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
124          hexdump(next_packet, length);          hexdump(g_next_packet, length);
125  #endif /*  */  #endif /*  */
126    
127          next_packet += length;          g_next_packet += length;
128          return rdp_s;          return rdp_s;
129  }  }
130    
# Line 98  rdp_init_data(int maxlen) Line 134  rdp_init_data(int maxlen)
134  {  {
135          STREAM s;          STREAM s;
136    
137          s = sec_init(encryption ? SEC_ENCRYPT : 0, maxlen + 18);          s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
138          s_push_layer(s, rdp_hdr, 18);          s_push_layer(s, rdp_hdr, 18);
139    
140          return s;          return s;
# Line 115  rdp_send_data(STREAM s, uint8 data_pdu_t Line 151  rdp_send_data(STREAM s, uint8 data_pdu_t
151    
152          out_uint16_le(s, length);          out_uint16_le(s, length);
153          out_uint16_le(s, (RDP_PDU_DATA | 0x10));          out_uint16_le(s, (RDP_PDU_DATA | 0x10));
154          out_uint16_le(s, (mcs_userid + 1001));          out_uint16_le(s, (g_mcs_userid + 1001));
155    
156          out_uint32_le(s, rdp_shareid);          out_uint32_le(s, g_rdp_shareid);
157          out_uint8(s, 0);        /* pad */          out_uint8(s, 0);        /* pad */
158          out_uint8(s, 1);        /* streamid */          out_uint8(s, 1);        /* streamid */
159          out_uint16_le(s, (length - 14));          out_uint16_le(s, (length - 14));
# Line 125  rdp_send_data(STREAM s, uint8 data_pdu_t Line 161  rdp_send_data(STREAM s, uint8 data_pdu_t
161          out_uint8(s, 0);        /* compress_type */          out_uint8(s, 0);        /* compress_type */
162          out_uint16(s, 0);       /* compress_len */          out_uint16(s, 0);       /* compress_len */
163    
164          sec_send(s, encryption ? SEC_ENCRYPT : 0);          sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
165  }  }
166    
167  /* Output a string in Unicode */  /* Output a string in Unicode */
168  void  void
169  rdp_out_unistr(STREAM s, char *string, int len)  rdp_out_unistr(STREAM s, char *string, int len)
170  {  {
171          int i = 0, j = 0;  #ifdef HAVE_ICONV
172            size_t ibl = strlen(string), obl = len + 2;
173            static iconv_t iconv_h = (iconv_t) - 1;
174            char *pin = string, *pout = (char *) s->p;
175    
176            memset(pout, 0, len + 4);
177    
178            if (g_iconv_works)
179            {
180                    if (iconv_h == (iconv_t) - 1)
181                    {
182                            size_t i = 1, o = 4;
183                            if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
184                            {
185                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
186                                            g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
187    
188                                    g_iconv_works = False;
189                                    rdp_out_unistr(s, string, len);
190                                    return;
191                            }
192                            if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
193                                (size_t) - 1)
194                            {
195                                    iconv_close(iconv_h);
196                                    iconv_h = (iconv_t) - 1;
197                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
198    
199                                    g_iconv_works = False;
200                                    rdp_out_unistr(s, string, len);
201                                    return;
202                            }
203                            pin = string;
204                            pout = (char *) s->p;
205                    }
206    
207          len += 2;                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
208                    {
209                            iconv_close(iconv_h);
210                            iconv_h = (iconv_t) - 1;
211                            warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
212    
213                            g_iconv_works = False;
214                            rdp_out_unistr(s, string, len);
215                            return;
216                    }
217    
218                    s->p += len + 2;
219    
220          while (i < len)          }
221            else
222    #endif
223          {          {
224                  s->p[i++] = string[j++];                  int i = 0, j = 0;
225                  s->p[i++] = 0;  
226                    len += 2;
227    
228                    while (i < len)
229                    {
230                            s->p[i++] = string[j++];
231                            s->p[i++] = 0;
232                    }
233    
234                    s->p += len;
235            }
236    }
237    
238    /* Input a string in Unicode
239     *
240     * Returns str_len of string
241     */
242    int
243    rdp_in_unistr(STREAM s, char *string, int uni_len)
244    {
245    #ifdef HAVE_ICONV
246            size_t ibl = uni_len, obl = uni_len;
247            char *pin = (char *) s->p, *pout = string;
248            static iconv_t iconv_h = (iconv_t) - 1;
249    
250            if (g_iconv_works)
251            {
252                    if (iconv_h == (iconv_t) - 1)
253                    {
254                            if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
255                            {
256                                    warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
257                                            WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
258    
259                                    g_iconv_works = False;
260                                    return rdp_in_unistr(s, string, uni_len);
261                            }
262                    }
263    
264                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
265                    {
266                            iconv_close(iconv_h);
267                            iconv_h = (iconv_t) - 1;
268                            warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
269    
270                            g_iconv_works = False;
271                            return rdp_in_unistr(s, string, uni_len);
272                    }
273    
274                    /* we must update the location of the current STREAM for future reads of s->p */
275                    s->p += uni_len;
276    
277                    return pout - string;
278          }          }
279            else
280    #endif
281            {
282                    int i = 0;
283    
284          s->p += len;                  while (i < uni_len / 2)
285                    {
286                            in_uint8a(s, &string[i++], 1);
287                            in_uint8s(s, 1);
288                    }
289    
290                    return i - 1;
291            }
292  }  }
293    
294    
295  /* Parse a logon info packet */  /* Parse a logon info packet */
296  static void  static void
297  rdp_send_logon_info(uint32 flags, char *domain, char *user,  rdp_send_logon_info(uint32 flags, char *domain, char *user,
298                      char *password, char *program, char *directory)                      char *password, char *program, char *directory)
299  {  {
300            char *ipaddr = tcp_get_address();
301          int len_domain = 2 * strlen(domain);          int len_domain = 2 * strlen(domain);
302          int len_user = 2 * strlen(user);          int len_user = 2 * strlen(user);
303          int len_password = 2 * strlen(password);          int len_password = 2 * strlen(password);
304          int len_program = 2 * strlen(program);          int len_program = 2 * strlen(program);
305          int len_directory = 2 * strlen(directory);          int len_directory = 2 * strlen(directory);
306          uint32 sec_flags = encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;          int len_ip = 2 * strlen(ipaddr);
307            int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
308            int packetlen = 0;
309            uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
310          STREAM s;          STREAM s;
311            time_t t = time(NULL);
312            time_t tzone;
313    
314            if (!g_use_rdp5 || 1 == g_server_rdp_version)
315            {
316                    DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
317    
318                    s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
319                                 + len_program + len_directory + 10);
320    
321                    out_uint32(s, 0);
322                    out_uint32_le(s, flags);
323                    out_uint16_le(s, len_domain);
324                    out_uint16_le(s, len_user);
325                    out_uint16_le(s, len_password);
326                    out_uint16_le(s, len_program);
327                    out_uint16_le(s, len_directory);
328                    rdp_out_unistr(s, domain, len_domain);
329                    rdp_out_unistr(s, user, len_user);
330                    rdp_out_unistr(s, password, len_password);
331                    rdp_out_unistr(s, program, len_program);
332                    rdp_out_unistr(s, directory, len_directory);
333            }
334            else
335            {
336    
337          s = sec_init(sec_flags, 18 + len_domain + len_user + len_password                  flags |= RDP_LOGON_BLOB;
338                       + len_program + len_directory + 10);                  DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
339                    packetlen = 4 + /* Unknown uint32 */
340                            4 +     /* flags */
341                            2 +     /* len_domain */
342                            2 +     /* len_user */
343                            (flags & RDP_LOGON_AUTO ? 2 : 0) +      /* len_password */
344                            (flags & RDP_LOGON_BLOB ? 2 : 0) +      /* Length of BLOB */
345                            2 +     /* len_program */
346                            2 +     /* len_directory */
347                            (0 < len_domain ? len_domain : 2) +     /* domain */
348                            len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
349                            (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
350                            (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 +     /* Unknown (2) */
351                            2 +     /* Client ip length */
352                            len_ip +        /* Client ip */
353                            2 +     /* DLL string length */
354                            len_dll +       /* DLL string */
355                            2 +     /* Unknown */
356                            2 +     /* Unknown */
357                            64 +    /* Time zone #0 */
358                            2 +     /* Unknown */
359                            64 +    /* Time zone #1 */
360                            32;     /* Unknown */
361    
362                    s = sec_init(sec_flags, packetlen);
363                    DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
364    
365                    out_uint32(s, 0);       /* Unknown */
366                    out_uint32_le(s, flags);
367                    out_uint16_le(s, len_domain);
368                    out_uint16_le(s, len_user);
369                    if (flags & RDP_LOGON_AUTO)
370                    {
371                            out_uint16_le(s, len_password);
372    
373                    }
374                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
375                    {
376                            out_uint16_le(s, 0);
377                    }
378                    out_uint16_le(s, len_program);
379                    out_uint16_le(s, len_directory);
380                    if (0 < len_domain)
381                            rdp_out_unistr(s, domain, len_domain);
382                    else
383                            out_uint16_le(s, 0);
384                    rdp_out_unistr(s, user, len_user);
385                    if (flags & RDP_LOGON_AUTO)
386                    {
387                            rdp_out_unistr(s, password, len_password);
388                    }
389                    if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
390                    {
391                            out_uint16_le(s, 0);
392                    }
393                    if (0 < len_program)
394                    {
395                            rdp_out_unistr(s, program, len_program);
396    
397                    }
398                    else
399                    {
400                            out_uint16_le(s, 0);
401                    }
402                    if (0 < len_directory)
403                    {
404                            rdp_out_unistr(s, directory, len_directory);
405                    }
406                    else
407                    {
408                            out_uint16_le(s, 0);
409                    }
410                    out_uint16_le(s, 2);
411                    out_uint16_le(s, len_ip + 2);   /* Length of client ip */
412                    rdp_out_unistr(s, ipaddr, len_ip);
413                    out_uint16_le(s, len_dll + 2);
414                    rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
415    
416                    tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
417                    out_uint32_le(s, tzone);
418    
419                    rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
420                    out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
421    
422                    out_uint32_le(s, 0x0a0000);
423                    out_uint32_le(s, 0x050000);
424                    out_uint32_le(s, 3);
425                    out_uint32_le(s, 0);
426                    out_uint32_le(s, 0);
427    
428                    rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
429                    out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
430    
431                    out_uint32_le(s, 0x30000);
432                    out_uint32_le(s, 0x050000);
433                    out_uint32_le(s, 2);
434                    out_uint32(s, 0);
435                    out_uint32_le(s, 0xffffffc4);
436                    out_uint32_le(s, 0xfffffffe);
437                    out_uint32_le(s, g_rdp5_performanceflags);
438                    out_uint32(s, 0);
439    
         out_uint32(s, 0);  
         out_uint32_le(s, flags);  
         out_uint16_le(s, len_domain);  
         out_uint16_le(s, len_user);  
         out_uint16_le(s, len_password);  
         out_uint16_le(s, len_program);  
         out_uint16_le(s, len_directory);  
         rdp_out_unistr(s, domain, len_domain);  
         rdp_out_unistr(s, user, len_user);  
         rdp_out_unistr(s, password, len_password);  
         rdp_out_unistr(s, program, len_program);  
         rdp_out_unistr(s, directory, len_directory);  
440    
441            }
442          s_mark_end(s);          s_mark_end(s);
443          sec_send(s, sec_flags);          sec_send(s, sec_flags);
444  }  }
# Line 196  rdp_send_control(uint16 action) Line 461  rdp_send_control(uint16 action)
461    
462  /* Send a synchronisation PDU */  /* Send a synchronisation PDU */
463  static void  static void
464  rdp_send_synchronise()  rdp_send_synchronise(void)
465  {  {
466          STREAM s;          STREAM s;
467    
# Line 230  rdp_send_input(uint32 time, uint16 messa Line 495  rdp_send_input(uint32 time, uint16 messa
495          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
496  }  }
497    
498    /* Send a client window information PDU */
499    void
500    rdp_send_client_window_status(int status)
501    {
502            STREAM s;
503            static int current_status = 1;
504    
505            if (current_status == status)
506                    return;
507    
508            s = rdp_init_data(12);
509    
510            out_uint32_le(s, status);
511    
512            switch (status)
513            {
514                    case 0: /* shut the server up */
515                            break;
516    
517                    case 1: /* receive data again */
518                            out_uint32_le(s, 0);    /* unknown */
519                            out_uint16_le(s, g_width);
520                            out_uint16_le(s, g_height);
521                            break;
522            }
523    
524            s_mark_end(s);
525            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
526            current_status = status;
527    }
528    
529    /* Send persistent bitmap cache enumeration PDU's */
530    static void
531    rdp_enum_bmpcache2(void)
532    {
533            STREAM s;
534            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
535            uint32 num_keys, offset, count, flags;
536    
537            offset = 0;
538            num_keys = pstcache_enumerate(2, keylist);
539    
540            while (offset < num_keys)
541            {
542                    count = MIN(num_keys - offset, 169);
543    
544                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
545    
546                    flags = 0;
547                    if (offset == 0)
548                            flags |= PDU_FLAG_FIRST;
549                    if (num_keys - offset <= 169)
550                            flags |= PDU_FLAG_LAST;
551    
552                    /* header */
553                    out_uint32_le(s, 0);
554                    out_uint16_le(s, count);
555                    out_uint16_le(s, 0);
556                    out_uint16_le(s, 0);
557                    out_uint16_le(s, 0);
558                    out_uint16_le(s, 0);
559                    out_uint16_le(s, num_keys);
560                    out_uint32_le(s, 0);
561                    out_uint32_le(s, flags);
562    
563                    /* list */
564                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
565    
566                    s_mark_end(s);
567                    rdp_send_data(s, 0x2b);
568    
569                    offset += 169;
570            }
571    }
572    
573  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
574  static void  static void
575  rdp_send_fonts(uint16 seq)  rdp_send_fonts(uint16 seq)
# Line 239  rdp_send_fonts(uint16 seq) Line 579  rdp_send_fonts(uint16 seq)
579          s = rdp_init_data(8);          s = rdp_init_data(8);
580    
581          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
582          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
583          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
584          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
585    
# Line 259  rdp_out_general_caps(STREAM s) Line 599  rdp_out_general_caps(STREAM s)
599          out_uint16_le(s, 0x200);        /* Protocol version */          out_uint16_le(s, 0x200);        /* Protocol version */
600          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
601          out_uint16(s, 0);       /* Compression types */          out_uint16(s, 0);       /* Compression types */
602          out_uint16(s, 0);       /* Pad */          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
603            /* Pad, according to T.128. 0x40d seems to
604               trigger
605               the server to start sending RDP5 packets.
606               However, the value is 0x1d04 with W2KTSK and
607               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
608               for sending such information in a padding
609               field.. */
610          out_uint16(s, 0);       /* Update capability */          out_uint16(s, 0);       /* Update capability */
611          out_uint16(s, 0);       /* Remote unshare capability */          out_uint16(s, 0);       /* Remote unshare capability */
612          out_uint16(s, 0);       /* Compression level */          out_uint16(s, 0);       /* Compression level */
# Line 273  rdp_out_bitmap_caps(STREAM s) Line 620  rdp_out_bitmap_caps(STREAM s)
620          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
621          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
622    
623          out_uint16_le(s, 8);    /* Preferred BPP */          out_uint16_le(s, g_server_depth);       /* Preferred colour depth */
624          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
625          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
626          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
627          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
628          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
629          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
630          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
631          out_uint16_le(s, bitmap_compression ? 1 : 0);   /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
632          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
633          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
634          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
# Line 293  rdp_out_order_caps(STREAM s) Line 640  rdp_out_order_caps(STREAM s)
640  {  {
641          uint8 order_caps[32];          uint8 order_caps[32];
642    
   
643          memset(order_caps, 0, 32);          memset(order_caps, 0, 32);
644          order_caps[0] = 1;      /* dest blt */          order_caps[0] = 1;      /* dest blt */
645          order_caps[1] = 1;      /* pat blt */          order_caps[1] = 1;      /* pat blt */
646          order_caps[2] = 1;      /* screen blt */          order_caps[2] = 1;      /* screen blt */
647          order_caps[3] = 1;      /* required for memblt? */          order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
648            order_caps[4] = 0;      /* triblt */
649          order_caps[8] = 1;      /* line */          order_caps[8] = 1;      /* line */
650          order_caps[9] = 1;      /* line */          order_caps[9] = 1;      /* line */
651          order_caps[10] = 1;     /* rect */          order_caps[10] = 1;     /* rect */
652          order_caps[11] = (desktop_save == False ? 0 : 1);       /* desksave */          order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
653          order_caps[13] = 1;     /* memblt */          order_caps[13] = 1;     /* memblt */
654          order_caps[14] = 1;     /* triblt */          order_caps[14] = 1;     /* triblt */
655            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
656            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
657          order_caps[22] = 1;     /* polyline */          order_caps[22] = 1;     /* polyline */
658            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
659            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
660          order_caps[27] = 1;     /* text2 */          order_caps[27] = 1;     /* text2 */
661          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
662          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
# Line 320  rdp_out_order_caps(STREAM s) Line 671  rdp_out_order_caps(STREAM s)
671          out_uint8p(s, order_caps, 32);  /* Orders supported */          out_uint8p(s, order_caps, 32);  /* Orders supported */
672          out_uint16_le(s, 0x6a1);        /* Text capability flags */          out_uint16_le(s, 0x6a1);        /* Text capability flags */
673          out_uint8s(s, 6);       /* Pad */          out_uint8s(s, 6);       /* Pad */
674          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 */
675          out_uint32(s, 0);       /* Unknown */          out_uint32(s, 0);       /* Unknown */
676          out_uint32_le(s, 0x4e4);        /* Unknown */          out_uint32_le(s, 0x4e4);        /* Unknown */
677  }  }
# Line 329  rdp_out_order_caps(STREAM s) Line 680  rdp_out_order_caps(STREAM s)
680  static void  static void
681  rdp_out_bmpcache_caps(STREAM s)  rdp_out_bmpcache_caps(STREAM s)
682  {  {
683            int Bpp;
684          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
685          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
686    
687            Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
688          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
689          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
690          out_uint16_le(s, 0x100);        /* max cell size */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
691          out_uint16_le(s, 0x12c);        /* entries */          out_uint16_le(s, 0x12c);        /* entries */
692          out_uint16_le(s, 0x400);        /* max cell size */          out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
693          out_uint16_le(s, 0x106);        /* entries */          out_uint16_le(s, 0x106);        /* entries */
694          out_uint16_le(s, 0x1000);       /* max cell size */          out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
695    }
696    
697    /* Output bitmap cache v2 capability set */
698    static void
699    rdp_out_bmpcache2_caps(STREAM s)
700    {
701            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
702            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
703    
704            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
705    
706            out_uint16_be(s, 3);    /* number of caches in this set */
707    
708            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
709            out_uint32_le(s, BMPCACHE2_C0_CELLS);
710            out_uint32_le(s, BMPCACHE2_C1_CELLS);
711            if (pstcache_init(2))
712            {
713                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
714            }
715            else
716            {
717                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
718            }
719            out_uint8s(s, 20);      /* other bitmap caches not used */
720  }  }
721    
722  /* Output control capability set */  /* Output control capability set */
# Line 400  rdp_out_colcache_caps(STREAM s) Line 778  rdp_out_colcache_caps(STREAM s)
778          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
779  }  }
780    
781  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
782          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
783          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784          0x00, 0x00, 0x00, 0x00, 0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
785          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
788          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
789          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790          0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792          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  
793  };  };
794    
795  /* Output unknown capability set */  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
796    
797    static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
798    
799    static uint8 caps_0x10[] = {
800            0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
801            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
802            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
803            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
804            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
805            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
806    };
807    
808    /* Output unknown capability sets */
809  static void  static void
810  rdp_out_unknown_caps(STREAM s)  rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
811  {  {
812          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
813          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
814    
815          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN - 4);          out_uint8p(s, caps, length - 4);
816  }  }
817    
818    #define RDP5_FLAG 0x0030
819  /* Send a confirm active PDU */  /* Send a confirm active PDU */
820  static void  static void
821  rdp_send_confirm_active()  rdp_send_confirm_active(void)
822  {  {
823          STREAM s;          STREAM s;
824            uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
825          uint16 caplen =          uint16 caplen =
826                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
827                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
828                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +                  RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
829                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE + RDP_CAPLEN_UNKNOWN + 4 /* w2k fix, why? */ ;                  RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
830                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
831                    4 /* w2k fix, why? */ ;
832    
833          s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));          s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
834    
835          out_uint32_le(s, rdp_shareid);          out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
836            out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
837            out_uint16_le(s, (g_mcs_userid + 1001));
838    
839            out_uint32_le(s, g_rdp_shareid);
840          out_uint16_le(s, 0x3ea);        /* userid */          out_uint16_le(s, 0x3ea);        /* userid */
841          out_uint16_le(s, sizeof(RDP_SOURCE));          out_uint16_le(s, sizeof(RDP_SOURCE));
842          out_uint16_le(s, caplen);          out_uint16_le(s, caplen);
# Line 457  rdp_send_confirm_active() Line 848  rdp_send_confirm_active()
848          rdp_out_general_caps(s);          rdp_out_general_caps(s);
849          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
850          rdp_out_order_caps(s);          rdp_out_order_caps(s);
851          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
852          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
853          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
854          rdp_out_control_caps(s);          rdp_out_control_caps(s);
855          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
856          rdp_out_share_caps(s);          rdp_out_share_caps(s);
857          rdp_out_unknown_caps(s);  
858            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
859            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
860            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
861            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
862    
863          s_mark_end(s);          s_mark_end(s);
864          rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);          sec_send(s, sec_flags);
865    }
866    
867    /* Process a general capability set */
868    static void
869    rdp_process_general_caps(STREAM s)
870    {
871            uint16 pad2octetsB;     /* rdp5 flags? */
872    
873            in_uint8s(s, 10);
874            in_uint16_le(s, pad2octetsB);
875    
876            if (!pad2octetsB)
877                    g_use_rdp5 = False;
878    }
879    
880    /* Process a bitmap capability set */
881    static void
882    rdp_process_bitmap_caps(STREAM s)
883    {
884            uint16 width, height, depth;
885    
886            in_uint16_le(s, depth);
887            in_uint8s(s, 6);
888    
889            in_uint16_le(s, width);
890            in_uint16_le(s, height);
891    
892            DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
893    
894            /*
895             * The server may limit depth and change the size of the desktop (for
896             * example when shadowing another session).
897             */
898            if (g_server_depth != depth)
899            {
900                    warning("Remote desktop does not support colour depth %d; falling back to %d\n",
901                            g_server_depth, depth);
902                    g_server_depth = depth;
903            }
904            if (g_width != width || g_height != height)
905            {
906                    warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
907                            width, height);
908                    g_width = width;
909                    g_height = height;
910                    ui_resize_window();
911            }
912    }
913    
914    /* Process server capabilities */
915    static void
916    rdp_process_server_caps(STREAM s, uint16 length)
917    {
918            int n;
919            uint8 *next, *start;
920            uint16 ncapsets, capset_type, capset_length;
921    
922            start = s->p;
923    
924            in_uint16_le(s, ncapsets);
925            in_uint8s(s, 2);        /* pad */
926    
927            for (n = 0; n < ncapsets; n++)
928            {
929                    if (s->p > start + length)
930                            return;
931    
932                    in_uint16_le(s, capset_type);
933                    in_uint16_le(s, capset_length);
934    
935                    next = s->p + capset_length - 4;
936    
937                    switch (capset_type)
938                    {
939                            case RDP_CAPSET_GENERAL:
940                                    rdp_process_general_caps(s);
941                                    break;
942    
943                            case RDP_CAPSET_BITMAP:
944                                    rdp_process_bitmap_caps(s);
945                                    break;
946                    }
947    
948                    s->p = next;
949            }
950  }  }
951    
952  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
# Line 474  static void Line 954  static void
954  process_demand_active(STREAM s)  process_demand_active(STREAM s)
955  {  {
956          uint8 type;          uint8 type;
957            uint16 len_src_descriptor, len_combined_caps;
958    
959          in_uint32_le(s, rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
960            in_uint16_le(s, len_src_descriptor);
961            in_uint16_le(s, len_combined_caps);
962            in_uint8s(s, len_src_descriptor);
963    
964          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid));          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
965            rdp_process_server_caps(s, len_combined_caps);
966    
967          rdp_send_confirm_active();          rdp_send_confirm_active();
968          rdp_send_synchronise();          rdp_send_synchronise();
# Line 486  process_demand_active(STREAM s) Line 971  process_demand_active(STREAM s)
971          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
972          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
973          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
974          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);
975          rdp_send_fonts(1);  
976          rdp_send_fonts(2);          if (g_use_rdp5)
977          rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 */          {
978                    rdp_enum_bmpcache2();
979                    rdp_send_fonts(3);
980            }
981            else
982            {
983                    rdp_send_fonts(1);
984                    rdp_send_fonts(2);
985            }
986    
987            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
988          reset_order_state();          reset_order_state();
989  }  }
990    
991    /* Process a colour pointer PDU */
992    void
993    process_colour_pointer_pdu(STREAM s)
994    {
995            uint16 x, y, width, height, cache_idx, masklen, datalen;
996            uint8 *mask, *data;
997            HCURSOR cursor;
998    
999            in_uint16_le(s, cache_idx);
1000            in_uint16_le(s, x);
1001            in_uint16_le(s, y);
1002            in_uint16_le(s, width);
1003            in_uint16_le(s, height);
1004            in_uint16_le(s, masklen);
1005            in_uint16_le(s, datalen);
1006            in_uint8p(s, data, datalen);
1007            in_uint8p(s, mask, masklen);
1008            cursor = ui_create_cursor(x, y, width, height, mask, data);
1009            ui_set_cursor(cursor);
1010            cache_put_cursor(cache_idx, cursor);
1011    }
1012    
1013    /* Process a cached pointer PDU */
1014    void
1015    process_cached_pointer_pdu(STREAM s)
1016    {
1017            uint16 cache_idx;
1018    
1019            in_uint16_le(s, cache_idx);
1020            ui_set_cursor(cache_get_cursor(cache_idx));
1021    }
1022    
1023    /* Process a system pointer PDU */
1024    void
1025    process_system_pointer_pdu(STREAM s)
1026    {
1027            uint16 system_pointer_type;
1028    
1029            in_uint16(s, system_pointer_type);
1030            switch (system_pointer_type)
1031            {
1032                    case RDP_NULL_POINTER:
1033                            ui_set_null_cursor();
1034                            break;
1035    
1036                    default:
1037                            unimpl("System pointer message 0x%x\n", system_pointer_type);
1038            }
1039    }
1040    
1041  /* Process a pointer PDU */  /* Process a pointer PDU */
1042  static void  static void
1043  process_pointer_pdu(STREAM s)  process_pointer_pdu(STREAM s)
1044  {  {
1045          uint16 message_type;          uint16 message_type;
1046          uint16 x, y, width, height, cache_idx, masklen, datalen;          uint16 x, y;
         uint8 *mask, *data;  
         HCURSOR cursor;  
1047    
1048          in_uint16_le(s, message_type);          in_uint16_le(s, message_type);
1049          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
# Line 515  process_pointer_pdu(STREAM s) Line 1058  process_pointer_pdu(STREAM s)
1058                          break;                          break;
1059    
1060                  case RDP_POINTER_COLOR:                  case RDP_POINTER_COLOR:
1061                          in_uint16_le(s, cache_idx);                          process_colour_pointer_pdu(s);
                         in_uint16_le(s, x);  
                         in_uint16_le(s, y);  
                         in_uint16_le(s, width);  
                         in_uint16_le(s, height);  
                         in_uint16_le(s, masklen);  
                         in_uint16_le(s, datalen);  
                         in_uint8p(s, data, datalen);  
                         in_uint8p(s, mask, masklen);  
                         cursor = ui_create_cursor(x, y, width, height, mask, data);  
                         ui_set_cursor(cursor);  
                         cache_put_cursor(cache_idx, cursor);  
1062                          break;                          break;
1063    
1064                  case RDP_POINTER_CACHED:                  case RDP_POINTER_CACHED:
1065                          in_uint16_le(s, cache_idx);                          process_cached_pointer_pdu(s);
1066                          ui_set_cursor(cache_get_cursor(cache_idx));                          break;
1067    
1068                    case RDP_POINTER_SYSTEM:
1069                            process_system_pointer_pdu(s);
1070                          break;                          break;
1071    
1072                  default:                  default:
1073                          DEBUG(("Pointer message 0x%x\n", message_type));                          unimpl("Pointer message 0x%x\n", message_type);
1074          }          }
1075  }  }
1076    
1077  /* Process bitmap updates */  /* Process bitmap updates */
1078  static void  void
1079  process_bitmap_updates(STREAM s)  process_bitmap_updates(STREAM s)
1080  {  {
1081          uint16 num_updates;          uint16 num_updates;
1082          uint16 left, top, right, bottom, width, height;          uint16 left, top, right, bottom, width, height;
1083          uint16 cx, cy, bpp, compress, bufsize, size;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1084          uint8 *data, *bmpdata;          uint8 *data, *bmpdata;
1085          int i;          int i;
1086    
# Line 560  process_bitmap_updates(STREAM s) Line 1095  process_bitmap_updates(STREAM s)
1095                  in_uint16_le(s, width);                  in_uint16_le(s, width);
1096                  in_uint16_le(s, height);                  in_uint16_le(s, height);
1097                  in_uint16_le(s, bpp);                  in_uint16_le(s, bpp);
1098                    Bpp = (bpp + 7) / 8;
1099                  in_uint16_le(s, compress);                  in_uint16_le(s, compress);
1100                  in_uint16_le(s, bufsize);                  in_uint16_le(s, bufsize);
1101    
1102                  cx = right - left + 1;                  cx = right - left + 1;
1103                  cy = bottom - top + 1;                  cy = bottom - top + 1;
1104    
1105                  DEBUG(("UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,cmp=%d)\n",                  DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
1106                         left, top, right, bottom, width, height, compress));                         left, top, right, bottom, width, height, Bpp, compress));
1107    
1108                  if (!compress)                  if (!compress)
1109                  {                  {
1110                          int y;                          int y;
1111                          bmpdata = xmalloc(width * height);                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1112                          for (y = 0; y < height; y++)                          for (y = 0; y < height; y++)
1113                          {                          {
1114                                  in_uint8a(s, &bmpdata[(height - y - 1) * width], width);                                  in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1115                                              width * Bpp);
1116                          }                          }
1117                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1118                          xfree(bmpdata);                          xfree(bmpdata);
1119                          continue;                          continue;
1120                  }                  }
1121    
                 in_uint8s(s, 2);        /* pad */  
                 in_uint16_le(s, size);  
                 in_uint8s(s, 4);        /* line_size, final_size */  
                 in_uint8p(s, data, size);  
1122    
1123                  bmpdata = xmalloc(width * height);                  if (compress & 0x400)
1124                  if (bitmap_decompress(bmpdata, width, height, data, size))                  {
1125                            size = bufsize;
1126                    }
1127                    else
1128                    {
1129                            in_uint8s(s, 2);        /* pad */
1130                            in_uint16_le(s, size);
1131                            in_uint8s(s, 4);        /* line_size, final_size */
1132                    }
1133                    in_uint8p(s, data, size);
1134                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1135                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1136                  {                  {
1137                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);                          ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1138                  }                  }
1139                    else
1140                    {
1141                            DEBUG_RDP5(("Failed to decompress data\n"));
1142                    }
1143    
1144                  xfree(bmpdata);                  xfree(bmpdata);
1145          }          }
1146  }  }
1147    
1148  /* Process a palette update */  /* Process a palette update */
1149  static void  void
1150  process_palette(STREAM s)  process_palette(STREAM s)
1151  {  {
1152          HCOLOURMAP hmap;          COLOURENTRY *entry;
1153          COLOURMAP map;          COLOURMAP map;
1154          uint8 *colours;          HCOLOURMAP hmap;
1155            int i;
1156    
1157          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1158          in_uint16_le(s, map.ncolours);          in_uint16_le(s, map.ncolours);
1159          in_uint8s(s, 2);        /* pad */          in_uint8s(s, 2);        /* pad */
1160          in_uint8p(s, colours, (map.ncolours * 3));  
1161          map.colours = (COLOURENTRY *) colours;          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1162    
1163            DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1164    
1165            for (i = 0; i < map.ncolours; i++)
1166            {
1167                    entry = &map.colours[i];
1168                    in_uint8(s, entry->red);
1169                    in_uint8(s, entry->green);
1170                    in_uint8(s, entry->blue);
1171            }
1172    
1173          hmap = ui_create_colourmap(&map);          hmap = ui_create_colourmap(&map);
1174          ui_set_colourmap(hmap);          ui_set_colourmap(hmap);
1175    
1176            xfree(map.colours);
1177  }  }
1178    
1179  /* Process an update PDU */  /* Process an update PDU */
1180  static void  static void
1181  process_update_pdu(STREAM s)  process_update_pdu(STREAM s)
1182  {  {
1183          uint16 update_type;          uint16 update_type, count;
1184    
1185          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1186    
1187            ui_begin_update();
1188          switch (update_type)          switch (update_type)
1189          {          {
1190                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
1191                          process_orders(s);                          in_uint8s(s, 2);        /* pad */
1192                            in_uint16_le(s, count);
1193                            in_uint8s(s, 2);        /* pad */
1194                            process_orders(s, count);
1195                          break;                          break;
1196    
1197                  case RDP_UPDATE_BITMAP:                  case RDP_UPDATE_BITMAP:
# Line 643  process_update_pdu(STREAM s) Line 1208  process_update_pdu(STREAM s)
1208                  default:                  default:
1209                          unimpl("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1210          }          }
1211            ui_end_update();
1212    }
1213    
1214    /* Process a disconnect PDU */
1215    void
1216    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1217    {
1218            in_uint32_le(s, *ext_disc_reason);
1219    
1220            DEBUG(("Received disconnect PDU\n"));
1221  }  }
1222    
1223  /* Process data PDU */  /* Process data PDU */
1224  static void  static BOOL
1225  process_data_pdu(STREAM s)  process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1226  {  {
1227          uint8 data_pdu_type;          uint8 data_pdu_type;
1228            uint8 ctype;
1229            uint16 clen;
1230            uint32 len;
1231    
1232            uint32 roff, rlen;
1233    
1234          in_uint8s(s, 8);        /* shareid, pad, streamid, length */          struct stream *ns = &(g_mppc_dict.ns);
1235    
1236            in_uint8s(s, 6);        /* shareid, pad, streamid */
1237            in_uint16(s, len);
1238          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1239          in_uint8s(s, 3);        /* compress_type, compress_len */          in_uint8(s, ctype);
1240            in_uint16(s, clen);
1241            clen -= 18;
1242    
1243            if (ctype & RDP_MPPC_COMPRESSED)
1244            {
1245                    if (len > RDP_MPPC_DICT_SIZE)
1246                            error("error decompressed packet size exceeds max\n");
1247                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1248                            error("error while decompressing packet\n");
1249    
1250                    /* len -= 18; */
1251    
1252                    /* allocate memory and copy the uncompressed data into the temporary stream */
1253                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1254    
1255                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1256    
1257                    ns->size = rlen;
1258                    ns->end = (ns->data + ns->size);
1259                    ns->p = ns->data;
1260                    ns->rdp_hdr = ns->p;
1261    
1262                    s = ns;
1263            }
1264    
1265          switch (data_pdu_type)          switch (data_pdu_type)
1266          {          {
# Line 662  process_data_pdu(STREAM s) Line 1268  process_data_pdu(STREAM s)
1268                          process_update_pdu(s);                          process_update_pdu(s);
1269                          break;                          break;
1270    
1271                    case RDP_DATA_PDU_CONTROL:
1272                            DEBUG(("Received Control PDU\n"));
1273                            break;
1274    
1275                    case RDP_DATA_PDU_SYNCHRONISE:
1276                            DEBUG(("Received Sync PDU\n"));
1277                            break;
1278    
1279                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1280                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1281                          break;                          break;
# Line 671  process_data_pdu(STREAM s) Line 1285  process_data_pdu(STREAM s)
1285                          break;                          break;
1286    
1287                  case RDP_DATA_PDU_LOGON:                  case RDP_DATA_PDU_LOGON:
1288                            DEBUG(("Received Logon PDU\n"));
1289                          /* User logged on */                          /* User logged on */
1290                          break;                          break;
1291    
1292                    case RDP_DATA_PDU_DISCONNECT:
1293                            process_disconnect_pdu(s, ext_disc_reason);
1294                            return True;
1295    
1296                  default:                  default:
1297                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1298          }          }
1299            return False;
1300    }
1301    
1302    /* Process redirect PDU from Session Directory */
1303    static BOOL
1304    process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1305    {
1306            uint32 len;
1307    
1308            /* these 2 bytes are unknown, seem to be zeros */
1309            in_uint8s(s, 2);
1310    
1311            /* read connection flags */
1312            in_uint32_le(s, g_redirect_flags);
1313    
1314            /* read length of ip string */
1315            in_uint32_le(s, len);
1316    
1317            /* read ip string */
1318            rdp_in_unistr(s, g_redirect_server, len);
1319    
1320            /* read length of cookie string */
1321            in_uint32_le(s, len);
1322    
1323            /* read cookie string (plain ASCII) */
1324            in_uint8a(s, g_redirect_cookie, len);
1325            g_redirect_cookie[len] = 0;
1326    
1327            /* read length of username string */
1328            in_uint32_le(s, len);
1329    
1330            /* read username string */
1331            rdp_in_unistr(s, g_redirect_username, len);
1332    
1333            /* read length of domain string */
1334            in_uint32_le(s, len);
1335    
1336            /* read domain string */
1337            rdp_in_unistr(s, g_redirect_domain, len);
1338    
1339            /* read length of password string */
1340            in_uint32_le(s, len);
1341    
1342            /* read password string */
1343            rdp_in_unistr(s, g_redirect_password, len);
1344    
1345            g_redirect = True;
1346    
1347            return True;
1348  }  }
1349    
1350  /* Process incoming packets */  /* Process incoming packets */
1351    /* nevers gets out of here till app is done */
1352  void  void
1353  rdp_main_loop()  rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1354    {
1355            while (rdp_loop(deactivated, ext_disc_reason))
1356                    ;
1357    }
1358    
1359    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1360    BOOL
1361    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1362  {  {
1363          uint8 type;          uint8 type;
1364            BOOL disc = False;      /* True when a disconnect PDU was received */
1365            BOOL cont = True;
1366          STREAM s;          STREAM s;
1367    
1368          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1369          {          {
1370                    s = rdp_recv(&type);
1371                    if (s == NULL)
1372                            return False;
1373                  switch (type)                  switch (type)
1374                  {                  {
1375                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1376                                  process_demand_active(s);                                  process_demand_active(s);
1377                                    *deactivated = False;
1378                                  break;                                  break;
   
1379                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1380                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1381                                    *deactivated = True;
1382                                    break;
1383                            case RDP_PDU_REDIRECT:
1384                                    return process_redirect_pdu(s);
1385                                  break;                                  break;
   
1386                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1387                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1388                                    break;
1389                            case 0:
1390                                  break;                                  break;
   
1391                          default:                          default:
1392                                  unimpl("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1393                  }                  }
1394                    if (disc)
1395                            return False;
1396                    cont = g_next_packet < s->end;
1397          }          }
1398            return True;
1399  }  }
1400    
1401  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
# Line 712  BOOL Line 1403  BOOL
1403  rdp_connect(char *server, uint32 flags, char *domain, char *password,  rdp_connect(char *server, uint32 flags, char *domain, char *password,
1404              char *command, char *directory)              char *command, char *directory)
1405  {  {
1406          if (!sec_connect(server))          if (!sec_connect(server, g_username))
1407                    return False;
1408    
1409            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1410            return True;
1411    }
1412    
1413    /* Establish a reconnection up to the RDP layer */
1414    BOOL
1415    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1416                  char *command, char *directory, char *cookie)
1417    {
1418            if (!sec_reconnect(server))
1419                  return False;                  return False;
1420    
1421          rdp_send_logon_info(flags, domain, username, password, command, directory);          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1422          return True;          return True;
1423  }  }
1424    
1425    /* Called during redirection to reset the state to support redirection */
1426    void
1427    rdp_reset_state(void)
1428    {
1429            g_next_packet = NULL;   /* reset the packet information */
1430            g_rdp_shareid = 0;
1431            sec_reset_state();
1432    }
1433    
1434  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1435  void  void
1436  rdp_disconnect()  rdp_disconnect(void)
1437  {  {
1438          sec_disconnect();          sec_disconnect();
1439  }  }

Legend:
Removed from v.176  
changed lines
  Added in v.1042

  ViewVC Help
Powered by ViewVC 1.1.26