/[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 861 by stargo, Sun Mar 13 17:40:51 2005 UTC revision 1238 by matthewc, Wed Jun 14 08:59:03 2006 UTC
# Line 44  extern BOOL g_polygon_ellipse_orders; Line 44  extern BOOL g_polygon_ellipse_orders;
44  extern BOOL g_use_rdp5;  extern BOOL g_use_rdp5;
45  extern uint16 g_server_rdp_version;  extern uint16 g_server_rdp_version;
46  extern uint32 g_rdp5_performanceflags;  extern uint32 g_rdp5_performanceflags;
47  extern int g_server_bpp;  extern int g_server_depth;
48  extern int g_width;  extern int g_width;
49  extern int g_height;  extern int g_height;
50  extern BOOL g_bitmap_cache;  extern BOOL g_bitmap_cache;
51  extern BOOL g_bitmap_cache_persist_enable;  extern BOOL g_bitmap_cache_persist_enable;
52    extern BOOL g_numlock_sync;
53    
54  uint8 *g_next_packet;  uint8 *g_next_packet;
55  uint32 g_rdp_shareid;  uint32 g_rdp_shareid;
56    
57  extern RDPCOMP g_mppc_dict;  extern RDPCOMP g_mppc_dict;
58    
59    /* Session Directory support */
60    extern BOOL g_redirect;
61    extern char g_redirect_server[64];
62    extern char g_redirect_domain[16];
63    extern char g_redirect_password[64];
64    extern char g_redirect_username[64];
65    extern char g_redirect_cookie[128];
66    extern uint32 g_redirect_flags;
67    /* END Session Directory support */
68    
69  #if WITH_DEBUG  #if WITH_DEBUG
70  static uint32 g_packetno;  static uint32 g_packetno;
71  #endif  #endif
72    
73    #ifdef HAVE_ICONV
74    static BOOL g_iconv_works = True;
75    #endif
76    
77  /* Receive an RDP packet */  /* Receive an RDP packet */
78  static STREAM  static STREAM
79  rdp_recv(uint8 * type)  rdp_recv(uint8 * type)
# Line 67  rdp_recv(uint8 * type) Line 82  rdp_recv(uint8 * type)
82          uint16 length, pdu_type;          uint16 length, pdu_type;
83          uint8 rdpver;          uint8 rdpver;
84    
85          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))          if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
86          {          {
87                  rdp_s = sec_recv(&rdpver);                  rdp_s = sec_recv(&rdpver);
88                  if (rdp_s == NULL)                  if (rdp_s == NULL)
# Line 157  rdp_out_unistr(STREAM s, char *string, i Line 172  rdp_out_unistr(STREAM s, char *string, i
172  #ifdef HAVE_ICONV  #ifdef HAVE_ICONV
173          size_t ibl = strlen(string), obl = len + 2;          size_t ibl = strlen(string), obl = len + 2;
174          static iconv_t iconv_h = (iconv_t) - 1;          static iconv_t iconv_h = (iconv_t) - 1;
175          char *pin = string, *pout;          char *pin = string, *pout = (char *) s->p;
 #ifdef B_ENDIAN  
         char ss[4096];          // FIXME: global MAX_BUF_SIZE macro need  
   
         pout = ss;  
 #else  
         pout = s->p;  
 #endif  
176    
177          memset(pout, 0, len + 4);          memset(pout, 0, len + 4);
178    
179          if (iconv_h == (iconv_t) - 1)          if (g_iconv_works)
180          {          {
181                  size_t i = 1, o = 4;                  if (iconv_h == (iconv_t) - 1)
                 if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)  
182                  {                  {
183                          printf("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",                          size_t i = 1, o = 4;
184                                 g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);                          if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
185                          return;                          {
186                                    warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
187                                            g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
188    
189                                    g_iconv_works = False;
190                                    rdp_out_unistr(s, string, len);
191                                    return;
192                            }
193                            if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
194                                (size_t) - 1)
195                            {
196                                    iconv_close(iconv_h);
197                                    iconv_h = (iconv_t) - 1;
198                                    warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
199    
200                                    g_iconv_works = False;
201                                    rdp_out_unistr(s, string, len);
202                                    return;
203                            }
204                            pin = string;
205                            pout = (char *) s->p;
206                  }                  }
207                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) == (size_t) - 1)  
208                    if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
209                  {                  {
210                          iconv_close(iconv_h);                          iconv_close(iconv_h);
211                          iconv_h = (iconv_t) - 1;                          iconv_h = (iconv_t) - 1;
212                          printf("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);                          warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
213    
214                            g_iconv_works = False;
215                            rdp_out_unistr(s, string, len);
216                          return;                          return;
217                  }                  }
                 pin = string;  
                 pout = (char *) s->p;  
         }  
218    
219          if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)                  s->p += len + 2;
         {  
                 iconv_close(iconv_h);  
                 iconv_h = (iconv_t) - 1;  
                 printf("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);  
                 return;  
         }  
220    
221  #ifdef B_ENDIAN          }
222          swab(ss, (char *) s->p, len + 4);          else
223  #endif  #endif
224            {
225                    int i = 0, j = 0;
226    
227          s->p += len + 2;                  len += 2;
   
 #else /*HAVE_ICONV undef */  
         int i = 0, j = 0;  
228    
229          len += 2;                  while (i < len)
230                    {
231                            s->p[i++] = string[j++];
232                            s->p[i++] = 0;
233                    }
234    
235          while (i < len)                  s->p += len;
         {  
                 s->p[i++] = string[j++];  
                 s->p[i++] = 0;  
236          }          }
   
         s->p += len;  
 #endif  
237  }  }
238    
239  /* Input a string in Unicode  /* Input a string in Unicode
# Line 226  rdp_in_unistr(STREAM s, char *string, in Line 245  rdp_in_unistr(STREAM s, char *string, in
245  {  {
246  #ifdef HAVE_ICONV  #ifdef HAVE_ICONV
247          size_t ibl = uni_len, obl = uni_len;          size_t ibl = uni_len, obl = uni_len;
248          char *pin, *pout = string;          char *pin = (char *) s->p, *pout = string;
249          static iconv_t iconv_h = (iconv_t) - 1;          static iconv_t iconv_h = (iconv_t) - 1;
 #ifdef B_ENDIAN  
         char ss[4096];          // FIXME: global MAX_BUF_SIZE macro need  
250    
251          swab((char *) s->p, ss, uni_len);          if (g_iconv_works)
         pin = ss;  
 #else  
         pin = s->p;  
 #endif  
   
         if (iconv_h == (iconv_t) - 1)  
252          {          {
253                  if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)                  if (iconv_h == (iconv_t) - 1)
254                  {                  {
255                          printf("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",                          if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
256                                 WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);                          {
257                          return 0;                                  warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
258                                            WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
259    
260                                    g_iconv_works = False;
261                                    return rdp_in_unistr(s, string, uni_len);
262                            }
263                  }                  }
         }  
264    
265          if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)                  if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
266          {                  {
267                  iconv_close(iconv_h);                          iconv_close(iconv_h);
268                  iconv_h = (iconv_t) - 1;                          iconv_h = (iconv_t) - 1;
269                  printf("rdp_in_unistr: iconv fail, errno %d\n", errno);                          warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
                 return 0;  
         }  
         return pout - string;  
 #else /* HAVE_ICONV undef */  
         int i = 0;  
270    
271          while (i < uni_len / 2)                          g_iconv_works = False;
272          {                          return rdp_in_unistr(s, string, uni_len);
273                  in_uint8a(s, &string[i++], 1);                  }
                 in_uint8s(s, 1);  
         }  
274    
275          return i - 1;                  /* we must update the location of the current STREAM for future reads of s->p */
276                    s->p += uni_len;
277    
278                    return pout - string;
279            }
280            else
281  #endif  #endif
282            {
283                    int i = 0;
284    
285                    while (i < uni_len / 2)
286                    {
287                            in_uint8a(s, &string[i++], 1);
288                            in_uint8s(s, 1);
289                    }
290    
291                    return i - 1;
292            }
293  }  }
294    
295    
# Line 288  rdp_send_logon_info(uint32 flags, char * Line 312  rdp_send_logon_info(uint32 flags, char *
312          time_t t = time(NULL);          time_t t = time(NULL);
313          time_t tzone;          time_t tzone;
314    
 #if 0  
         /* enable rdp compression */  
         /* some problems still exist with rdp5 */  
         flags |= RDP_COMPRESSION;  
 #endif  
   
315          if (!g_use_rdp5 || 1 == g_server_rdp_version)          if (!g_use_rdp5 || 1 == g_server_rdp_version)
316          {          {
317                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));                  DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
# Line 478  rdp_send_input(uint32 time, uint16 messa Line 496  rdp_send_input(uint32 time, uint16 messa
496          rdp_send_data(s, RDP_DATA_PDU_INPUT);          rdp_send_data(s, RDP_DATA_PDU_INPUT);
497  }  }
498    
499  /* Inform the server on the contents of the persistent bitmap cache */  /* Send a client window information PDU */
500    void
501    rdp_send_client_window_status(int status)
502    {
503            STREAM s;
504            static int current_status = 1;
505    
506            if (current_status == status)
507                    return;
508    
509            s = rdp_init_data(12);
510    
511            out_uint32_le(s, status);
512    
513            switch (status)
514            {
515                    case 0: /* shut the server up */
516                            break;
517    
518                    case 1: /* receive data again */
519                            out_uint32_le(s, 0);    /* unknown */
520                            out_uint16_le(s, g_width);
521                            out_uint16_le(s, g_height);
522                            break;
523            }
524    
525            s_mark_end(s);
526            rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
527            current_status = status;
528    }
529    
530    /* Send persistent bitmap cache enumeration PDU's */
531  static void  static void
532  rdp_enum_bmpcache2(void)  rdp_enum_bmpcache2(void)
533  {  {
# Line 572  rdp_out_bitmap_caps(STREAM s) Line 621  rdp_out_bitmap_caps(STREAM s)
621          out_uint16_le(s, RDP_CAPSET_BITMAP);          out_uint16_le(s, RDP_CAPSET_BITMAP);
622          out_uint16_le(s, RDP_CAPLEN_BITMAP);          out_uint16_le(s, RDP_CAPLEN_BITMAP);
623    
624          out_uint16_le(s, g_server_bpp); /* Preferred BPP */          out_uint16_le(s, g_server_depth);       /* Preferred colour depth */
625          out_uint16_le(s, 1);    /* Receive 1 BPP */          out_uint16_le(s, 1);    /* Receive 1 BPP */
626          out_uint16_le(s, 1);    /* Receive 4 BPP */          out_uint16_le(s, 1);    /* Receive 4 BPP */
627          out_uint16_le(s, 1);    /* Receive 8 BPP */          out_uint16_le(s, 1);    /* Receive 8 BPP */
# Line 636  rdp_out_bmpcache_caps(STREAM s) Line 685  rdp_out_bmpcache_caps(STREAM s)
685          out_uint16_le(s, RDP_CAPSET_BMPCACHE);          out_uint16_le(s, RDP_CAPSET_BMPCACHE);
686          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);          out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
687    
688          Bpp = (g_server_bpp + 7) / 8;          Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
689          out_uint8s(s, 24);      /* unused */          out_uint8s(s, 24);      /* unused */
690          out_uint16_le(s, 0x258);        /* entries */          out_uint16_le(s, 0x258);        /* entries */
691          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */          out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
# Line 655  rdp_out_bmpcache2_caps(STREAM s) Line 704  rdp_out_bmpcache2_caps(STREAM s)
704    
705          out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */          out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);        /* version */
706    
707          out_uint16_le(s, 0x0300);       /* flags? number of caches? */          out_uint16_be(s, 3);    /* number of caches in this set */
708    
709            /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
710          out_uint32_le(s, BMPCACHE2_C0_CELLS);          out_uint32_le(s, BMPCACHE2_C0_CELLS);
711          out_uint32_le(s, BMPCACHE2_C1_CELLS);          out_uint32_le(s, BMPCACHE2_C1_CELLS);
712          if (pstcache_init(2))          if (pstcache_init(2))
# Line 832  rdp_process_general_caps(STREAM s) Line 882  rdp_process_general_caps(STREAM s)
882  static void  static void
883  rdp_process_bitmap_caps(STREAM s)  rdp_process_bitmap_caps(STREAM s)
884  {  {
885          uint16 width, height, bpp;          uint16 width, height, depth;
886    
887          in_uint16_le(s, bpp);          in_uint16_le(s, depth);
888          in_uint8s(s, 6);          in_uint8s(s, 6);
889    
890          in_uint16_le(s, width);          in_uint16_le(s, width);
891          in_uint16_le(s, height);          in_uint16_le(s, height);
892    
893          DEBUG(("setting desktop size and bpp to: %dx%dx%d\n", width, height, bpp));          DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
894    
895          /*          /*
896           * The server may limit bpp and change the size of the desktop (for           * The server may limit depth and change the size of the desktop (for
897           * example when shadowing another session).           * example when shadowing another session).
898           */           */
899          if (g_server_bpp != bpp)          if (g_server_depth != depth)
900          {          {
901                  warning("colour depth changed from %d to %d\n", g_server_bpp, bpp);                  warning("Remote desktop does not support colour depth %d; falling back to %d\n",
902                  g_server_bpp = bpp;                          g_server_depth, depth);
903                    g_server_depth = depth;
904          }          }
905          if (g_width != width || g_height != height)          if (g_width != width || g_height != height)
906          {          {
907                  warning("screen size changed from %dx%d to %dx%d\n", g_width, g_height,                  warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
908                          width, height);                          width, height);
909                  g_width = width;                  g_width = width;
910                  g_height = height;                  g_height = height;
# Line 862  rdp_process_bitmap_caps(STREAM s) Line 913  rdp_process_bitmap_caps(STREAM s)
913  }  }
914    
915  /* Process server capabilities */  /* Process server capabilities */
916  void  static void
917  rdp_process_server_caps(STREAM s, uint16 length)  rdp_process_server_caps(STREAM s, uint16 length)
918  {  {
919          int n;          int n;
# Line 921  process_demand_active(STREAM s) Line 972  process_demand_active(STREAM s)
972          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */          rdp_recv(&type);        /* RDP_PDU_SYNCHRONIZE */
973          rdp_recv(&type);        /* RDP_CTL_COOPERATE */          rdp_recv(&type);        /* RDP_CTL_COOPERATE */
974          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */          rdp_recv(&type);        /* RDP_CTL_GRANT_CONTROL */
975          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);          rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0,
976                           g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0);
977    
978          if (g_use_rdp5)          if (g_use_rdp5)
979          {          {
# Line 1197  process_data_pdu(STREAM s, uint32 * ext_ Line 1249  process_data_pdu(STREAM s, uint32 * ext_
1249                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)                  if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
1250                          error("error while decompressing packet\n");                          error("error while decompressing packet\n");
1251    
1252                  //len -= 18;                  /* len -= 18; */
1253    
1254                  /* allocate memory and copy the uncompressed data into the temporary stream */                  /* allocate memory and copy the uncompressed data into the temporary stream */
1255                  ns->data = (uint8 *) xrealloc(ns->data, rlen);                  ns->data = (uint8 *) xrealloc(ns->data, rlen);
# Line 1241  process_data_pdu(STREAM s, uint32 * ext_ Line 1293  process_data_pdu(STREAM s, uint32 * ext_
1293    
1294                  case RDP_DATA_PDU_DISCONNECT:                  case RDP_DATA_PDU_DISCONNECT:
1295                          process_disconnect_pdu(s, ext_disc_reason);                          process_disconnect_pdu(s, ext_disc_reason);
1296                          return True;  
1297                            /* We used to return true and disconnect immediately here, but
1298                             * Windows Vista sends a disconnect PDU with reason 0 when
1299                             * reconnecting to a disconnected session, and MSTSC doesn't
1300                             * drop the connection.  I think we should just save the status.
1301                             */
1302                            break;
1303    
1304                  default:                  default:
1305                          unimpl("data PDU %d\n", data_pdu_type);                          unimpl("data PDU %d\n", data_pdu_type);
# Line 1249  process_data_pdu(STREAM s, uint32 * ext_ Line 1307  process_data_pdu(STREAM s, uint32 * ext_
1307          return False;          return False;
1308  }  }
1309    
1310    /* Process redirect PDU from Session Directory */
1311    static BOOL
1312    process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
1313    {
1314            uint32 len;
1315    
1316            /* these 2 bytes are unknown, seem to be zeros */
1317            in_uint8s(s, 2);
1318    
1319            /* read connection flags */
1320            in_uint32_le(s, g_redirect_flags);
1321    
1322            /* read length of ip string */
1323            in_uint32_le(s, len);
1324    
1325            /* read ip string */
1326            rdp_in_unistr(s, g_redirect_server, len);
1327    
1328            /* read length of cookie string */
1329            in_uint32_le(s, len);
1330    
1331            /* read cookie string (plain ASCII) */
1332            in_uint8a(s, g_redirect_cookie, len);
1333            g_redirect_cookie[len] = 0;
1334    
1335            /* read length of username string */
1336            in_uint32_le(s, len);
1337    
1338            /* read username string */
1339            rdp_in_unistr(s, g_redirect_username, len);
1340    
1341            /* read length of domain string */
1342            in_uint32_le(s, len);
1343    
1344            /* read domain string */
1345            rdp_in_unistr(s, g_redirect_domain, len);
1346    
1347            /* read length of password string */
1348            in_uint32_le(s, len);
1349    
1350            /* read password string */
1351            rdp_in_unistr(s, g_redirect_password, len);
1352    
1353            g_redirect = True;
1354    
1355            return True;
1356    }
1357    
1358  /* Process incoming packets */  /* Process incoming packets */
1359  /* nevers gets out of here till app is done */  /* nevers gets out of here till app is done */
1360  void  void
# Line 1282  rdp_loop(BOOL * deactivated, uint32 * ex Line 1388  rdp_loop(BOOL * deactivated, uint32 * ex
1388                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));                                  DEBUG(("RDP_PDU_DEACTIVATE\n"));
1389                                  *deactivated = True;                                  *deactivated = True;
1390                                  break;                                  break;
1391                            case RDP_PDU_REDIRECT:
1392                                    return process_redirect_pdu(s);
1393                                    break;
1394                          case RDP_PDU_DATA:                          case RDP_PDU_DATA:
1395                                  disc = process_data_pdu(s, ext_disc_reason);                                  disc = process_data_pdu(s, ext_disc_reason);
1396                                  break;                                  break;
# Line 1309  rdp_connect(char *server, uint32 flags, Line 1418  rdp_connect(char *server, uint32 flags,
1418          return True;          return True;
1419  }  }
1420    
1421    /* Establish a reconnection up to the RDP layer */
1422    BOOL
1423    rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
1424                  char *command, char *directory, char *cookie)
1425    {
1426            if (!sec_reconnect(server))
1427                    return False;
1428    
1429            rdp_send_logon_info(flags, domain, g_username, password, command, directory);
1430            return True;
1431    }
1432    
1433    /* Called during redirection to reset the state to support redirection */
1434    void
1435    rdp_reset_state(void)
1436    {
1437            g_next_packet = NULL;   /* reset the packet information */
1438            g_rdp_shareid = 0;
1439            sec_reset_state();
1440    }
1441    
1442  /* Disconnect from the RDP layer */  /* Disconnect from the RDP layer */
1443  void  void
1444  rdp_disconnect(void)  rdp_disconnect(void)

Legend:
Removed from v.861  
changed lines
  Added in v.1238

  ViewVC Help
Powered by ViewVC 1.1.26