/[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 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 905 by jdmeijer, Fri May 20 22:09:32 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          len += 2;          memset(pout, 0, len + 4);
167    
168          while (i < len)          if (g_iconv_works)
169          {          {
170                  s->p[i++] = string[j++];                  if (iconv_h == (iconv_t) - 1)
171                  s->p[i++] = 0;                  {
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          s->p += len;                  len += 2;
217    
218                    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            if (g_iconv_works)
241            {
242                    if (iconv_h == (iconv_t) - 1)
243                    {
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                    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          out_uint32(s, 0);                  }
384          out_uint32_le(s, flags);                  else
385          out_uint16_le(s, len_domain);                  {
386          out_uint16_le(s, len_user);                          out_uint16_le(s, 0);
387          out_uint16_le(s, len_password);                  }
388          out_uint16_le(s, len_program);                  if (0 < len_directory)
389          out_uint16_le(s, len_directory);                  {
390          rdp_out_unistr(s, domain,    len_domain);                          rdp_out_unistr(s, directory, len_directory);
391          rdp_out_unistr(s, user,      len_user);                  }
392          rdp_out_unistr(s, password,  len_password);                  else
393          rdp_out_unistr(s, program,   len_program);                  {
394          rdp_out_unistr(s, directory, len_directory);                          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    
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    
490            s = rdp_init_data(12);
491    
492            out_uint32_le(s, status);
493    
494            switch (status)
495            {
496                    case 0: /* shut the server up */
497                            break;
498    
499                    case 1: /* receive data again */
500                            out_uint32_le(s, 0);    /* unknown */
501                            out_uint16_le(s, g_width);
502                            out_uint16_le(s, g_height);
503                            break;
504            }
505    
506            s_mark_end(s);
507            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
508    }
509    
510    /* Send persistent bitmap cache enumeration PDU's */
511    static void
512    rdp_enum_bmpcache2(void)
513    {
514            STREAM s;
515            HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
516            uint32 num_keys, offset, count, flags;
517    
518            offset = 0;
519            num_keys = pstcache_enumerate(2, keylist);
520    
521            while (offset < num_keys)
522            {
523                    count = MIN(num_keys - offset, 169);
524    
525                    s = rdp_init_data(24 + count * sizeof(HASH_KEY));
526    
527                    flags = 0;
528                    if (offset == 0)
529                            flags |= PDU_FLAG_FIRST;
530                    if (num_keys - offset <= 169)
531                            flags |= PDU_FLAG_LAST;
532    
533                    /* header */
534                    out_uint32_le(s, 0);
535                    out_uint16_le(s, count);
536                    out_uint16_le(s, 0);
537                    out_uint16_le(s, 0);
538                    out_uint16_le(s, 0);
539                    out_uint16_le(s, 0);
540                    out_uint16_le(s, num_keys);
541                    out_uint32_le(s, 0);
542                    out_uint32_le(s, flags);
543    
544                    /* list */
545                    out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
546    
547                    s_mark_end(s);
548                    rdp_send_data(s, 0x2b);
549    
550                    offset += 169;
551            }
552    }
553    
554  /* Send an (empty) font information PDU */  /* Send an (empty) font information PDU */
555  static void rdp_send_fonts(uint16 seq)  static void
556    rdp_send_fonts(uint16 seq)
557  {  {
558          STREAM s;          STREAM s;
559    
560          s = rdp_init_data(8);          s = rdp_init_data(8);
561    
562          out_uint16(s, 0);       /* number of fonts */          out_uint16(s, 0);       /* number of fonts */
563          out_uint16_le(s, 0x3e); /* unknown */          out_uint16_le(s, 0);    /* pad? */
564          out_uint16_le(s, seq);  /* unknown */          out_uint16_le(s, seq);  /* unknown */
565          out_uint16_le(s, 0x32); /* entry size */          out_uint16_le(s, 0x32); /* entry size */
566    
# Line 236  static void rdp_send_fonts(uint16 seq) Line 569  static void rdp_send_fonts(uint16 seq)
569  }  }
570    
571  /* Output general capability set */  /* Output general capability set */
572  static void rdp_out_general_caps(STREAM s)  static void
573    rdp_out_general_caps(STREAM s)
574  {  {
575          out_uint16_le(s, RDP_CAPSET_GENERAL);          out_uint16_le(s, RDP_CAPSET_GENERAL);
576          out_uint16_le(s, RDP_CAPLEN_GENERAL);          out_uint16_le(s, RDP_CAPLEN_GENERAL);
577    
578          out_uint16_le(s, 1);    /* OS major type */          out_uint16_le(s, 1);    /* OS major type */
579          out_uint16_le(s, 3);    /* OS minor type */          out_uint16_le(s, 3);    /* OS minor type */
580          out_uint16_le(s, 0x200); /* Protocol version */          out_uint16_le(s, 0x200);        /* Protocol version */
581          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
582          out_uint16(s, 0);       /* Compression types */          out_uint16(s, 0);       /* Compression types */
583          out_uint16(s, 0);       /* Pad */          out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
584            /* Pad, according to T.128. 0x40d seems to
585               trigger
586               the server to start sending RDP5 packets.
587               However, the value is 0x1d04 with W2KTSK and
588               NT4MS. Hmm.. Anyway, thankyou, Microsoft,
589               for sending such information in a padding
590               field.. */
591          out_uint16(s, 0);       /* Update capability */          out_uint16(s, 0);       /* Update capability */
592          out_uint16(s, 0);       /* Remote unshare capability */          out_uint16(s, 0);       /* Remote unshare capability */
593          out_uint16(s, 0);       /* Compression level */          out_uint16(s, 0);       /* Compression level */
# Line 254  static void rdp_out_general_caps(STREAM Line 595  static void rdp_out_general_caps(STREAM
595  }  }
596    
597  /* Output bitmap capability set */  /* Output bitmap capability set */
598  static void rdp_out_bitmap_caps(STREAM s)  static void
599    rdp_out_bitmap_caps(STREAM s)
600  {  {
601          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
602          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
603    
604          out_uint16_le(s, 8);    /* Preferred BPP */          out_uint16_le(s, g_server_bpp); /* Preferred BPP */
605          out_uint16(s, 1);       /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
606          out_uint16(s, 1);       /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
607          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
608          out_uint16_le(s, 800);  /* Desktop width */          out_uint16_le(s, 800);  /* Desktop width */
609          out_uint16_le(s, 600);  /* Desktop height */          out_uint16_le(s, 600);  /* Desktop height */
610          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
611          out_uint16(s, 0);       /* Allow resize */          out_uint16(s, 1);       /* Allow resize */
612          out_uint16_le(s, 1);    /* Support compression */          out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
613          out_uint16(s, 0);       /* Unknown */          out_uint16(s, 0);       /* Unknown */
614          out_uint16_le(s, 1);    /* Unknown */          out_uint16_le(s, 1);    /* Unknown */
615          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
616  }  }
617    
618  /* Output order capability set */  /* Output order capability set */
619  static void rdp_out_order_caps(STREAM s)  static void
620    rdp_out_order_caps(STREAM s)
621  {  {
622          uint8 order_caps[32];          uint8 order_caps[32];
623    
624          memset(order_caps, orders, 32);          memset(order_caps, 0, 32);
625            order_caps[0] = 1;      /* dest blt */
626            order_caps[1] = 1;      /* pat blt */
627            order_caps[2] = 1;      /* screen blt */
628            order_caps[3] = (g_bitmap_cache ? 1 : 0);       /* memblt */
629            order_caps[4] = 0;      /* triblt */
630            order_caps[8] = 1;      /* line */
631            order_caps[9] = 1;      /* line */
632            order_caps[10] = 1;     /* rect */
633            order_caps[11] = (g_desktop_save ? 1 : 0);      /* desksave */
634            order_caps[13] = 1;     /* memblt */
635            order_caps[14] = 1;     /* triblt */
636            order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
637            order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
638            order_caps[22] = 1;     /* polyline */
639            order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
640            order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
641            order_caps[27] = 1;     /* text2 */
642          out_uint16_le(s, RDP_CAPSET_ORDER);          out_uint16_le(s, RDP_CAPSET_ORDER);
643          out_uint16_le(s, RDP_CAPLEN_ORDER);          out_uint16_le(s, RDP_CAPLEN_ORDER);
644    
# Line 289  static void rdp_out_order_caps(STREAM s) Line 648  static void rdp_out_order_caps(STREAM s)
648          out_uint16(s, 0);       /* Pad */          out_uint16(s, 0);       /* Pad */
649          out_uint16_le(s, 1);    /* Max order level */          out_uint16_le(s, 1);    /* Max order level */
650          out_uint16_le(s, 0x147);        /* Number of fonts */          out_uint16_le(s, 0x147);        /* Number of fonts */
651          out_uint16_le(s, 0x2a);         /* Capability flags */          out_uint16_le(s, 0x2a); /* Capability flags */
652          out_uint8p(s, order_caps, 32);  /* Orders supported */          out_uint8p(s, order_caps, 32);  /* Orders supported */
653          out_uint16_le(s, 0x6a1);        /* Text capability flags */          out_uint16_le(s, 0x6a1);        /* Text capability flags */
654          out_uint8s(s, 6);       /* Pad */          out_uint8s(s, 6);       /* Pad */
655          out_uint32(s, 0x38400); /* Desktop cache size */          out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);        /* Desktop cache size */
656          out_uint32(s, 0);       /* Unknown */          out_uint32(s, 0);       /* Unknown */
657          out_uint32(s, 0x4e4);   /* Unknown */          out_uint32_le(s, 0x4e4);        /* Unknown */
658  }  }
659    
660  /* Output bitmap cache capability set */  /* Output bitmap cache capability set */
661  static void rdp_out_bmpcache_caps(STREAM s)  static void
662    rdp_out_bmpcache_caps(STREAM s)
663  {  {
664            int Bpp;
665          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
666          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
667    
668          out_uint8s(s, 24); /* unused */          Bpp = (g_server_bpp + 7) / 8;
669          out_uint16_le(s, 0x258); /* entries */          out_uint8s(s, 24);      /* unused */
670          out_uint16_le(s, 0x100); /* max cell size */          out_uint16_le(s, 0x258);        /* entries */
671          out_uint16_le(s, 0x12c); /* entries */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
672          out_uint16_le(s, 0x400); /* max cell size */          out_uint16_le(s, 0x12c);        /* entries */
673          out_uint16_le(s, 0x106); /* entries */          out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
674          out_uint16_le(s, 0x1000); /* max cell size */          out_uint16_le(s, 0x106);        /* entries */
675            out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
676    }
677    
678    /* Output bitmap cache v2 capability set */
679    static void
680    rdp_out_bmpcache2_caps(STREAM s)
681    {
682            out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
683            out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
684    
685            out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
686    
687            out_uint16_be(s, 3);    /* number of caches in this set */
688    
689            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
690            out_uint32_le(s, BMPCACHE2_C0_CELLS);
691            out_uint32_le(s, BMPCACHE2_C1_CELLS);
692            if (pstcache_init(2))
693            {
694                    out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
695            }
696            else
697            {
698                    out_uint32_le(s, BMPCACHE2_C2_CELLS);
699            }
700            out_uint8s(s, 20);      /* other bitmap caches not used */
701  }  }
702    
703  /* Output control capability set */  /* Output control capability set */
704  static void rdp_out_control_caps(STREAM s)  static void
705    rdp_out_control_caps(STREAM s)
706  {  {
707          out_uint16_le(s, RDP_CAPSET_CONTROL);          out_uint16_le(s, RDP_CAPSET_CONTROL);
708          out_uint16_le(s, RDP_CAPLEN_CONTROL);          out_uint16_le(s, RDP_CAPLEN_CONTROL);
# Line 326  static void rdp_out_control_caps(STREAM Line 714  static void rdp_out_control_caps(STREAM
714  }  }
715    
716  /* Output activation capability set */  /* Output activation capability set */
717  static void rdp_out_activate_caps(STREAM s)  static void
718    rdp_out_activate_caps(STREAM s)
719  {  {
720          out_uint16_le(s, RDP_CAPSET_ACTIVATE);          out_uint16_le(s, RDP_CAPSET_ACTIVATE);
721          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);          out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
# Line 338  static void rdp_out_activate_caps(STREAM Line 727  static void rdp_out_activate_caps(STREAM
727  }  }
728    
729  /* Output pointer capability set */  /* Output pointer capability set */
730  static void rdp_out_pointer_caps(STREAM s)  static void
731    rdp_out_pointer_caps(STREAM s)
732  {  {
733          out_uint16_le(s, RDP_CAPSET_POINTER);          out_uint16_le(s, RDP_CAPSET_POINTER);
734          out_uint16_le(s, RDP_CAPLEN_POINTER);          out_uint16_le(s, RDP_CAPLEN_POINTER);
# Line 348  static void rdp_out_pointer_caps(STREAM Line 738  static void rdp_out_pointer_caps(STREAM
738  }  }
739    
740  /* Output share capability set */  /* Output share capability set */
741  static void rdp_out_share_caps(STREAM s)  static void
742    rdp_out_share_caps(STREAM s)
743  {  {
744          out_uint16_le(s, RDP_CAPSET_SHARE);          out_uint16_le(s, RDP_CAPSET_SHARE);
745          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 749  static void rdp_out_share_caps(STREAM s)
749  }  }
750    
751  /* Output colour cache capability set */  /* Output colour cache capability set */
752  static void rdp_out_colcache_caps(STREAM s)  static void
753    rdp_out_colcache_caps(STREAM s)
754  {  {
755          out_uint16_le(s, RDP_CAPSET_COLCACHE);          out_uint16_le(s, RDP_CAPSET_COLCACHE);
756          out_uint16_le(s, RDP_CAPLEN_COLCACHE);          out_uint16_le(s, RDP_CAPLEN_COLCACHE);
# Line 367  static void rdp_out_colcache_caps(STREAM Line 759  static void rdp_out_colcache_caps(STREAM
759          out_uint16(s, 0);       /* pad */          out_uint16(s, 0);       /* pad */
760  }  }
761    
762  static uint8 canned_caps[] = {  static uint8 caps_0x0d[] = {
763  0x01,0x00,0x00,0x00,0x09,0x04,0x00,0x00,0x04,          0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
764  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,          0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
765  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,          0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
766  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
767  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
768  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x08,0x00,0x01,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769  0x00,0x00,0x00,0x0E,0x00,0x08,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x34,0x00,0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
770  0x00,0x04,0x00,0xFE,0x00,0x04,0x00,0xFE,0x00,0x08,0x00,0xFE,0x00,0x08,0x00,0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
771  0x00,0x10,0x00,0xFE,0x00,0x20,0x00,0xFE,0x00,0x40,0x00,0xFE,0x00,0x80,0x00,0xFE,          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772  0x00,0x00,0x01,0x40,0x00,0x00,0x08,0x00,0x01,0x00,0x01,0x02,0x00,0x00,0x00          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
773            0x00, 0x00, 0x00, 0x00
774  };  };
775    
776  /* Output unknown capability set */  static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
777  static void rdp_out_unknown_caps(STREAM s)  
778    static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
779    
780    static uint8 caps_0x10[] = {
781            0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
782            0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
783            0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
784            0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
785            0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
786            0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
787    };
788    
789    /* Output unknown capability sets */
790    static void
791    rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
792  {  {
793          out_uint16_le(s, RDP_CAPSET_UNKNOWN);          out_uint16_le(s, id);
794          out_uint16_le(s, 0x58);          out_uint16_le(s, length);
795            
796          out_uint8p(s, canned_caps, RDP_CAPLEN_UNKNOWN-4);          out_uint8p(s, caps, length - 4);
797  }  }
798    
799    #define RDP5_FLAG 0x0030
800  /* Send a confirm active PDU */  /* Send a confirm active PDU */
801  static void rdp_send_confirm_active()  static void
802    rdp_send_confirm_active(void)
803  {  {
804          STREAM s;          STREAM s;
805          uint16 caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER          uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
806                  + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + RDP_CAPLEN_ACTIVATE          uint16 caplen =
807                  + RDP_CAPLEN_CONTROL + RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE                  RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
808                  + RDP_CAPLEN_UNKNOWN;                  RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
809                    RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
810                    RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
811                    0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
812                    4 /* w2k fix, why? */ ;
813    
814            s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
815    
816            out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
817            out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));      /* Version 1 */
818            out_uint16_le(s, (g_mcs_userid + 1001));
819    
820          s = rdp_init(14 + caplen + sizeof(RDP_SOURCE));          out_uint32_le(s, g_rdp_shareid);
821            out_uint16_le(s, 0x3ea);        /* userid */
         out_uint32_le(s, rdp_shareid);  
         out_uint16_le(s, 0x3ea); /* userid */  
822          out_uint16_le(s, sizeof(RDP_SOURCE));          out_uint16_le(s, sizeof(RDP_SOURCE));
823          out_uint16_le(s, caplen);          out_uint16_le(s, caplen);
824    
825          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));          out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
826          out_uint16_le(s, 0xd); /* num_caps */          out_uint16_le(s, 0xd);  /* num_caps */
827          out_uint8s(s, 2);     /* pad */          out_uint8s(s, 2);       /* pad */
828    
829          rdp_out_general_caps(s);          rdp_out_general_caps(s);
830          rdp_out_bitmap_caps(s);          rdp_out_bitmap_caps(s);
831          rdp_out_order_caps(s);          rdp_out_order_caps(s);
832          rdp_out_bmpcache_caps(s);          g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
833          rdp_out_colcache_caps(s);          rdp_out_colcache_caps(s);
834          rdp_out_activate_caps(s);          rdp_out_activate_caps(s);
835          rdp_out_control_caps(s);          rdp_out_control_caps(s);
836          rdp_out_pointer_caps(s);          rdp_out_pointer_caps(s);
837          rdp_out_share_caps(s);          rdp_out_share_caps(s);
838          rdp_out_unknown_caps(s);  
839            rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
840            rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
841            rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
842            rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
843    
844          s_mark_end(s);          s_mark_end(s);
845          rdp_send(s, RDP_PDU_CONFIRM_ACTIVE);          sec_send(s, sec_flags);
846    }
847    
848    /* Process a general capability set */
849    static void
850    rdp_process_general_caps(STREAM s)
851    {
852            uint16 pad2octetsB;     /* rdp5 flags? */
853    
854            in_uint8s(s, 10);
855            in_uint16_le(s, pad2octetsB);
856    
857            if (!pad2octetsB)
858                    g_use_rdp5 = False;
859    }
860    
861    /* Process a bitmap capability set */
862    static void
863    rdp_process_bitmap_caps(STREAM s)
864    {
865            uint16 width, height, bpp;
866    
867            in_uint16_le(s, bpp);
868            in_uint8s(s, 6);
869    
870            in_uint16_le(s, width);
871            in_uint16_le(s, height);
872    
873            DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));
874    
875            /*
876             * The server may limit bpp and change the size of the desktop (for
877             * example when shadowing another session).
878             */
879            if (g_server_bpp != bpp)
880            {
881                    warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);
882                    g_server_bpp = bpp;
883            }
884            if (g_width != width || g_height != height)
885            {
886                    warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,
887                            width, height);
888                    g_width = width;
889                    g_height = height;
890                    ui_resize_window();
891            }
892    }
893    
894    /* Process server capabilities */
895    void
896    rdp_process_server_caps(STREAM s, uint16 length)
897    {
898            int n;
899            uint8 *next, *start;
900            uint16 ncapsets, capset_type, capset_length;
901    
902            start = s->p;
903    
904            in_uint16_le(s, ncapsets);
905            in_uint8s(s, 2);        /* pad */
906    
907            for (n = 0; n < ncapsets; n++)
908            {
909                    if (s->p > start + length)
910                            return;
911    
912                    in_uint16_le(s, capset_type);
913                    in_uint16_le(s, capset_length);
914    
915                    next = s->p + capset_length - 4;
916    
917                    switch (capset_type)
918                    {
919                            case RDP_CAPSET_GENERAL:
920                                    rdp_process_general_caps(s);
921                                    break;
922    
923                            case RDP_CAPSET_BITMAP:
924                                    rdp_process_bitmap_caps(s);
925                                    break;
926                    }
927    
928                    s->p = next;
929            }
930  }  }
931    
932  /* Respond to a demand active PDU */  /* Respond to a demand active PDU */
933  static void process_demand_active(STREAM s)  static void
934    process_demand_active(STREAM s)
935  {  {
936          uint8 type;          uint8 type;
937            uint16 len_src_descriptor, len_combined_caps;
938    
939          in_uint32_le(s, rdp_shareid);          in_uint32_le(s, g_rdp_shareid);
940            in_uint16_le(s, len_src_descriptor);
941            in_uint16_le(s, len_combined_caps);
942            in_uint8s(s, len_src_descriptor);
943    
944          DEBUG("DEMAND_ACTIVE(id=0x%x)\n", rdp_shareid);          DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
945            rdp_process_server_caps(s, len_combined_caps);
946    
947          rdp_send_confirm_active();          rdp_send_confirm_active();
948          rdp_send_synchronise();          rdp_send_synchronise();
949          rdp_send_control(RDP_CTL_COOPERATE);          rdp_send_control(RDP_CTL_COOPERATE);
950          rdp_send_control(RDP_CTL_REQUEST_CONTROL);          rdp_send_control(RDP_CTL_REQUEST_CONTROL);
951          rdp_recv(&type); // RDP_PDU_SYNCHRONIZE          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
952          rdp_recv(&type); // RDP_CTL_COOPERATE          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
953          rdp_recv(&type); // RDP_CTL_GRANT_CONTROL          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
954          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);
955          rdp_send_fonts(1);  
956          rdp_send_fonts(2);          if (g_use_rdp5)
957          rdp_recv(&type); // RDP_PDU_UNKNOWN 0x28          {
958                    rdp_enum_bmpcache2();
959                    rdp_send_fonts(3);
960            }
961            else
962            {
963                    rdp_send_fonts(1);
964                    rdp_send_fonts(2);
965            }
966    
967            rdp_recv(&type);        /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
968          reset_order_state();          reset_order_state();
969  }  }
970    
971    /* Process a colour pointer PDU */
972    void
973    process_colour_pointer_pdu(STREAM s)
974    {
975            uint16 x, y, width, height, cache_idx, masklen, datalen;
976            uint8 *mask, *data;
977            HCURSOR cursor;
978    
979            in_uint16_le(s, cache_idx);
980            in_uint16_le(s, x);
981            in_uint16_le(s, y);
982            in_uint16_le(s, width);
983            in_uint16_le(s, height);
984            in_uint16_le(s, masklen);
985            in_uint16_le(s, datalen);
986            in_uint8p(s, data, datalen);
987            in_uint8p(s, mask, masklen);
988            cursor = ui_create_cursor(x, y, width, height, mask, data);
989            ui_set_cursor(cursor);
990            cache_put_cursor(cache_idx, cursor);
991    }
992    
993    /* Process a cached pointer PDU */
994    void
995    process_cached_pointer_pdu(STREAM s)
996    {
997            uint16 cache_idx;
998    
999            in_uint16_le(s, cache_idx);
1000            ui_set_cursor(cache_get_cursor(cache_idx));
1001    }
1002    
1003    /* Process a system pointer PDU */
1004    void
1005    process_system_pointer_pdu(STREAM s)
1006    {
1007            uint16 system_pointer_type;
1008    
1009            in_uint16(s, system_pointer_type);
1010            switch (system_pointer_type)
1011            {
1012                    case RDP_NULL_POINTER:
1013                            ui_set_null_cursor();
1014                            break;
1015    
1016                    default:
1017                            unimpl("System pointer message 0x%x\n", system_pointer_type);
1018            }
1019    }
1020    
1021  /* Process a pointer PDU */  /* Process a pointer PDU */
1022  static void process_pointer_pdu(STREAM s)  static void
1023    process_pointer_pdu(STREAM s)
1024  {  {
1025          uint16 message_type;          uint16 message_type;
1026          uint16 x, y;          uint16 x, y;
1027    
1028          in_uint16_le(s, message_type);          in_uint16_le(s, message_type);
1029          in_uint8s(s, 2); /* pad */          in_uint8s(s, 2);        /* pad */
1030    
1031          switch (message_type)          switch (message_type)
1032          {          {
# Line 465  static void process_pointer_pdu(STREAM s Line 1037  static void process_pointer_pdu(STREAM s
1037                                  ui_move_pointer(x, y);                                  ui_move_pointer(x, y);
1038                          break;                          break;
1039    
1040                    case RDP_POINTER_COLOR:
1041                            process_colour_pointer_pdu(s);
1042                            break;
1043    
1044                    case RDP_POINTER_CACHED:
1045                            process_cached_pointer_pdu(s);
1046                            break;
1047    
1048                    case RDP_POINTER_SYSTEM:
1049                            process_system_pointer_pdu(s);
1050                            break;
1051    
1052                  default:                  default:
1053                          DEBUG("Pointer message 0x%x\n", message_type);                          unimpl("Pointer message 0x%x\n", message_type);
1054          }          }
1055  }  }
1056    
1057  /* Process bitmap updates */  /* Process bitmap updates */
1058  static void process_bitmap_updates(STREAM s)  void
1059    process_bitmap_updates(STREAM s)
1060  {  {
1061          uint16 num_updates;          uint16 num_updates;
1062          uint16 left, top, right, bottom, width, height;          uint16 left, top, right, bottom, width, height;
1063          uint16 cx, cy, bpp, compress, bufsize, size;          uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
1064          uint8 *data, *rawdata;          uint8 *data, *bmpdata;
1065          int i;          int i;
1066    
1067          in_uint16_le(s, num_updates);          in_uint16_le(s, num_updates);
# Line 490  static void process_bitmap_updates(STREA Line 1075  static void process_bitmap_updates(STREA
1075                  in_uint16_le(s, width);                  in_uint16_le(s, width);
1076                  in_uint16_le(s, height);                  in_uint16_le(s, height);
1077                  in_uint16_le(s, bpp);                  in_uint16_le(s, bpp);
1078                    Bpp = (bpp + 7) / 8;
1079                  in_uint16_le(s, compress);                  in_uint16_le(s, compress);
1080                  in_uint16_le(s, bufsize);                  in_uint16_le(s, bufsize);
1081    
1082                  cx = right - left + 1;                  cx = right - left + 1;
1083                  cy = bottom - top + 1;                  cy = bottom - top + 1;
1084    
1085                  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",
1086                          left, top, right, bottom, width, height, compress);                         left, top, right, bottom, width, height, Bpp, compress));
1087    
1088                  if (!compress)                  if (!compress)
1089                  {                  {
1090                          in_uint8p(s, data, bufsize);                          int y;
1091                          ui_paint_bitmap(left, top, cx, cy, width, height, data);                          bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1092                          return;                          for (y = 0; y < height; y++)
1093                            {
1094                                    in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
1095                                              width * Bpp);
1096                            }
1097                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1098                            xfree(bmpdata);
1099                            continue;
1100                  }                  }
1101    
                 in_uint8s(s, 2); /* pad */  
                 in_uint16_le(s, size);  
                 in_uint8s(s, 4); /* line_size, final_size */  
                 in_uint8p(s, data, size);  
1102    
1103                  rawdata = xmalloc(width * height);                  if (compress & 0x400)
1104                  if (bitmap_decompress(rawdata, width, height, data, size))                  {
1105                            size = bufsize;
1106                    }
1107                    else
1108                    {
1109                            in_uint8s(s, 2);        /* pad */
1110                            in_uint16_le(s, size);
1111                            in_uint8s(s, 4);        /* line_size, final_size */
1112                    }
1113                    in_uint8p(s, data, size);
1114                    bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1115                    if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1116                    {
1117                            ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
1118                    }
1119                    else
1120                  {                  {
1121                          ui_paint_bitmap(left, top, cx, cy, width, height,                          DEBUG_RDP5(("Failed to decompress data\n"));
                                         rawdata);  
1122                  }                  }
1123    
1124                  xfree(rawdata);                  xfree(bmpdata);
1125          }          }
1126  }  }
1127    
1128  /* Process a palette update */  /* Process a palette update */
1129  static void process_palette(STREAM s)  void
1130    process_palette(STREAM s)
1131  {  {
1132          HCOLOURMAP hmap;          COLOURENTRY *entry;
1133          COLOURMAP map;          COLOURMAP map;
1134            HCOLOURMAP hmap;
1135            int i;
1136    
1137            in_uint8s(s, 2);        /* pad */
1138            in_uint16_le(s, map.ncolours);
1139            in_uint8s(s, 2);        /* pad */
1140    
1141          in_uint8s(s, 2); /* pad */          map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1142          in_uint16_le(s, map.ncolours);  
1143          in_uint8s(s, 2); /* pad */          DEBUG(("PALETTE(c=%d)\n", map.ncolours));
1144          in_uint8p(s, (uint8 *)map.colours, (map.ncolours * 3));  
1145            for (i = 0; i < map.ncolours; i++)
1146            {
1147                    entry = &map.colours[i];
1148                    in_uint8(s, entry->red);
1149                    in_uint8(s, entry->green);
1150                    in_uint8(s, entry->blue);
1151            }
1152    
1153          hmap = ui_create_colourmap(&map);          hmap = ui_create_colourmap(&map);
1154          ui_set_colourmap(hmap);          ui_set_colourmap(hmap);
1155    
1156            xfree(map.colours);
1157  }  }
1158    
1159  /* Process an update PDU */  /* Process an update PDU */
1160  static void process_update_pdu(STREAM s)  static void
1161    process_update_pdu(STREAM s)
1162  {  {
1163          uint16 update_type;          uint16 update_type, count;
1164    
1165          in_uint16_le(s, update_type);          in_uint16_le(s, update_type);
1166    
1167            ui_begin_update();
1168          switch (update_type)          switch (update_type)
1169          {          {
1170                  case RDP_UPDATE_ORDERS:                  case RDP_UPDATE_ORDERS:
1171                          process_orders(s);                          in_uint8s(s, 2);        /* pad */
1172                            in_uint16_le(s, count);
1173                            in_uint8s(s, 2);        /* pad */
1174                            process_orders(s, count);
1175                          break;                          break;
1176    
1177                  case RDP_UPDATE_BITMAP:                  case RDP_UPDATE_BITMAP:
# Line 562  static void process_update_pdu(STREAM s) Line 1186  static void process_update_pdu(STREAM s)
1186                          break;                          break;
1187    
1188                  default:                  default:
1189                          NOTIMP("update %d\n", update_type);                          unimpl("update %d\n", update_type);
1190          }          }
1191            ui_end_update();
1192    }
1193    
1194    /* Process a disconnect PDU */
1195    void
1196    process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
1197    {
1198            in_uint32_le(s, *ext_disc_reason);
1199    
1200            DEBUG(("Received disconnect PDU\n"));
1201  }  }
1202    
1203  /* Process data PDU */  /* Process data PDU */
1204  static void process_data_pdu(STREAM s)  static BOOL
1205    process_data_pdu(STREAM s, uint32 * ext_disc_reason)
1206  {  {
1207          uint8 data_pdu_type;          uint8 data_pdu_type;
1208            uint8 ctype;
1209            uint16 clen;
1210            uint32 len;
1211    
1212            uint32 roff, rlen;
1213    
1214          in_uint8s(s, 8); /* shareid, pad, streamid, length */          struct stream *ns = &(g_mppc_dict.ns);
1215    
1216            in_uint8s(s, 6);        /* shareid, pad, streamid */
1217            in_uint16(s, len);
1218          in_uint8(s, data_pdu_type);          in_uint8(s, data_pdu_type);
1219          in_uint8s(s, 3); /* compress_type, compress_len */          in_uint8(s, ctype);
1220            in_uint16(s, clen);
1221            clen -= 18;
1222    
1223            if (ctype & RDP_MPPC_COMPRESSED)
1224            {
1225                    if (len > RDP_MPPC_DICT_SIZE)
1226                            error("error decompressed packet size exceeds max\n");
1227                    if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1228                            error("error while decompressing packet\n");
1229    
1230                    /* len -= 18; */
1231    
1232                    /* allocate memory and copy the uncompressed data into the temporary stream */
1233                    ns->data = (uint8 *) xrealloc(ns->data, rlen);
1234    
1235                    memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
1236    
1237                    ns->size = rlen;
1238                    ns->end = (ns->data + ns->size);
1239                    ns->p = ns->data;
1240                    ns->rdp_hdr = ns->p;
1241    
1242                    s = ns;
1243            }
1244    
1245          switch (data_pdu_type)          switch (data_pdu_type)
1246          {          {
# Line 582  static void process_data_pdu(STREAM s) Line 1248  static void process_data_pdu(STREAM s)
1248                          process_update_pdu(s);                          process_update_pdu(s);
1249                          break;                          break;
1250    
1251                    case RDP_DATA_PDU_CONTROL:
1252                            DEBUG(("Received Control PDU\n"));
1253                            break;
1254    
1255                    case RDP_DATA_PDU_SYNCHRONISE:
1256                            DEBUG(("Received Sync PDU\n"));
1257                            break;
1258    
1259                  case RDP_DATA_PDU_POINTER:                  case RDP_DATA_PDU_POINTER:
1260                          process_pointer_pdu(s);                          process_pointer_pdu(s);
1261                          break;                          break;
# Line 591  static void process_data_pdu(STREAM s) Line 1265  static void process_data_pdu(STREAM s)
1265                          break;                          break;
1266    
1267                  case RDP_DATA_PDU_LOGON:                  case RDP_DATA_PDU_LOGON:
1268                            DEBUG(("Received Logon PDU\n"));
1269                          /* User logged on */                          /* User logged on */
1270                          break;                          break;
1271    
1272                    case RDP_DATA_PDU_DISCONNECT:
1273                            process_disconnect_pdu(s, ext_disc_reason);
1274                            return True;
1275    
1276                  default:                  default:
1277                          NOTIMP("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
1278          }          }
1279            return False;
1280  }  }
1281    
1282  /* Process incoming packets */  /* Process incoming packets */
1283  void rdp_main_loop()  /* nevers gets out of here till app is done */
1284    void
1285    rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1286    {
1287            while (rdp_loop(deactivated, ext_disc_reason))
1288                    ;
1289    }
1290    
1291    /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
1292    BOOL
1293    rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
1294  {  {
1295          uint8 type;          uint8 type;
1296            BOOL disc = False;      /* True when a disconnect PDU was received */
1297            BOOL cont = True;
1298          STREAM s;          STREAM s;
1299    
1300          while ((s = rdp_recv(&type)) != NULL)          while (cont)
1301          {          {
1302                    s = rdp_recv(&type);
1303                    if (s == NULL)
1304                            return False;
1305                  switch (type)                  switch (type)
1306                  {                  {
1307                          case RDP_PDU_DEMAND_ACTIVE:                          case RDP_PDU_DEMAND_ACTIVE:
1308                                  process_demand_active(s);                                  process_demand_active(s);
1309                                    *deactivated = False;
1310                                  break;                                  break;
   
1311                          case RDP_PDU_DEACTIVATE:                          case RDP_PDU_DEACTIVATE:
1312                                    DEBUG(("RDP_PDU_DEACTIVATE\n"));
1313                                    *deactivated = True;
1314                                  break;                                  break;
   
1315                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1316                                  process_data_pdu(s);                                  disc = process_data_pdu(s, ext_disc_reason);
1317                                    break;
1318                            case 0:
1319                                  break;                                  break;
   
1320                          default:                          default:
1321                                  NOTIMP("PDU %d\n", type);                                  unimpl("PDU %d\n", type);
1322                  }                  }
1323                    if (disc)
1324                            return False;
1325                    cont = g_next_packet < s->end;
1326          }          }
1327            return True;
1328  }  }
1329    
1330  /* Establish a connection up to the RDP layer */  /* Establish a connection up to the RDP layer */
1331  BOOL rdp_connect(char *server)  BOOL
1332    rdp_connect(char *server, uint32 flags, char *domain, char *password,
1333                char *command, char *directory)
1334  {  {
1335          if (!sec_connect(server))          if (!sec_connect(server, g_username))
1336                  return False;                  return False;
1337    
1338          rdp_send_logon_info(0x33, "", username, "", "", "");          rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1339          return True;          return True;
1340  }  }
1341    
1342  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1343  void rdp_disconnect()  void
1344    rdp_disconnect(void)
1345  {  {
1346          sec_disconnect();          sec_disconnect();
1347  }  }
   

Legend:
Removed from v.10  
changed lines
  Added in v.905

  ViewVC Help
Powered by ViewVC 1.1.26