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

Legend:
Removed from v.21  
changed lines
  Added in v.907

  ViewVC Help
Powered by ViewVC 1.1.26