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

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

  ViewVC Help
Powered by ViewVC 1.1.26