ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rdp.c
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 8 -*-
00002    rdesktop: A Remote Desktop Protocol client.
00003    Protocol services - RDP layer
00004    Copyright (C) Matthew Chapman 1999-2005
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License along
00017    with this program; if not, write to the Free Software Foundation, Inc.,
00018    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019 */
00020 
00021 #include <precomp.h>
00022 
00023 
00024 extern uint16 g_mcs_userid;
00025 extern char g_username[];
00026 extern char g_codepage[];
00027 extern BOOL g_bitmap_compression;
00028 extern BOOL g_orders;
00029 extern BOOL g_encryption;
00030 extern BOOL g_desktop_save;
00031 extern BOOL g_polygon_ellipse_orders;
00032 extern BOOL g_use_rdp5;
00033 extern uint16 g_server_rdp_version;
00034 extern uint32 g_rdp5_performanceflags;
00035 extern int g_server_depth;
00036 extern int g_width;
00037 extern int g_height;
00038 extern BOOL g_bitmap_cache;
00039 extern BOOL g_bitmap_cache_persist_enable;
00040 
00041 uint8 *g_next_packet;
00042 uint32 g_rdp_shareid;
00043 
00044 extern RDPCOMP g_mppc_dict;
00045 
00046 /* Session Directory support */
00047 extern BOOL g_redirect;
00048 extern char g_redirect_server[64];
00049 extern char g_redirect_domain[16];
00050 extern char g_redirect_password[64];
00051 extern char g_redirect_username[64];
00052 extern char g_redirect_cookie[128];
00053 extern uint32 g_redirect_flags;
00054 /* END Session Directory support */
00055 
00056 #ifdef WITH_DEBUG
00057 static uint32 g_packetno;
00058 #endif
00059 
00060 #ifdef HAVE_ICONV
00061 static BOOL g_iconv_works = True;
00062 #endif
00063 
00064 /* Receive an RDP packet */
00065 static STREAM
00066 rdp_recv(uint8 * type)
00067 {
00068     static STREAM rdp_s;
00069     uint16 length, pdu_type;
00070     uint8 rdpver;
00071 
00072     if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
00073     {
00074         rdp_s = sec_recv(&rdpver);
00075         if (rdp_s == NULL)
00076             return NULL;
00077         if (rdpver == 0xff)
00078         {
00079             g_next_packet = rdp_s->end;
00080             *type = 0;
00081             return rdp_s;
00082         }
00083         else if (rdpver != 3)
00084         {
00085             /* rdp5_process should move g_next_packet ok */
00086             rdp5_process(rdp_s);
00087             *type = 0;
00088             return rdp_s;
00089         }
00090 
00091         g_next_packet = rdp_s->p;
00092     }
00093     else
00094     {
00095         rdp_s->p = g_next_packet;
00096     }
00097 
00098     in_uint16_le(rdp_s, length);
00099     /* 32k packets are really 8, keepalive fix */
00100     if (length == 0x8000)
00101     {
00102         g_next_packet += 8;
00103         *type = 0;
00104         return rdp_s;
00105     }
00106     in_uint16_le(rdp_s, pdu_type);
00107     in_uint8s(rdp_s, 2);    /* userid */
00108     *type = pdu_type & 0xf;
00109 
00110 #ifdef WITH_DEBUG
00111     DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
00112     hexdump(g_next_packet, length);
00113 #endif /*  */
00114 
00115     g_next_packet += length;
00116     return rdp_s;
00117 }
00118 
00119 /* Initialise an RDP data packet */
00120 static STREAM
00121 rdp_init_data(int maxlen)
00122 {
00123     STREAM s = NULL;
00124 
00125     s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
00126     s_push_layer(s, rdp_hdr, 18);
00127 
00128     return s;
00129 }
00130 
00131 /* Send an RDP data packet */
00132 static void
00133 rdp_send_data(STREAM s, uint8 data_pdu_type)
00134 {
00135     uint16 length;
00136 
00137     s_pop_layer(s, rdp_hdr);
00138     length = s->end - s->p;
00139 
00140     out_uint16_le(s, length);
00141     out_uint16_le(s, (RDP_PDU_DATA | 0x10));
00142     out_uint16_le(s, (g_mcs_userid + 1001));
00143 
00144     out_uint32_le(s, g_rdp_shareid);
00145     out_uint8(s, 0);    /* pad */
00146     out_uint8(s, 1);    /* streamid */
00147     out_uint16_le(s, (length - 14));
00148     out_uint8(s, data_pdu_type);
00149     out_uint8(s, 0);    /* compress_type */
00150     out_uint16(s, 0);   /* compress_len */
00151 
00152     sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
00153 }
00154 
00155 /* Output a string in Unicode */
00156 void
00157 rdp_out_unistr(STREAM s, char *string, int len)
00158 {
00159 #ifdef HAVE_ICONV
00160     size_t ibl = strlen(string), obl = len + 2;
00161     static iconv_t iconv_h = (iconv_t) - 1;
00162     char *pin = string, *pout = (char *) s->p;
00163 
00164     memset(pout, 0, len + 4);
00165 
00166     if (g_iconv_works)
00167     {
00168         if (iconv_h == (iconv_t) - 1)
00169         {
00170             size_t i = 1, o = 4;
00171             if ((iconv_h = iconv_open(WINDOWS_CODEPAGE, g_codepage)) == (iconv_t) - 1)
00172             {
00173                 warning("rdp_out_unistr: iconv_open[%s -> %s] fail %d\n",
00174                     g_codepage, WINDOWS_CODEPAGE, (int) iconv_h);
00175 
00176                 g_iconv_works = False;
00177                 rdp_out_unistr(s, string, len);
00178                 return;
00179             }
00180             if (iconv(iconv_h, (ICONV_CONST char **) &pin, &i, &pout, &o) ==
00181                 (size_t) - 1)
00182             {
00183                 iconv_close(iconv_h);
00184                 iconv_h = (iconv_t) - 1;
00185                 warning("rdp_out_unistr: iconv(1) fail, errno %d\n", errno);
00186 
00187                 g_iconv_works = False;
00188                 rdp_out_unistr(s, string, len);
00189                 return;
00190             }
00191             pin = string;
00192             pout = (char *) s->p;
00193         }
00194 
00195         if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
00196         {
00197             iconv_close(iconv_h);
00198             iconv_h = (iconv_t) - 1;
00199             warning("rdp_out_unistr: iconv(2) fail, errno %d\n", errno);
00200 
00201             g_iconv_works = False;
00202             rdp_out_unistr(s, string, len);
00203             return;
00204         }
00205 
00206         s->p += len + 2;
00207 
00208     }
00209     else
00210 #endif
00211     {
00212         int i = 0, j = 0;
00213 
00214         len += 2;
00215 
00216         while (i < len)
00217         {
00218             s->p[i++] = string[j++];
00219             s->p[i++] = 0;
00220         }
00221 
00222         s->p += len;
00223     }
00224 }
00225 
00226 /* Input a string in Unicode
00227  *
00228  * Returns str_len of string
00229  */
00230 int
00231 rdp_in_unistr(STREAM s, char *string, int uni_len)
00232 {
00233 #ifdef HAVE_ICONV
00234     size_t ibl = uni_len, obl = uni_len;
00235     char *pin = (char *) s->p, *pout = string;
00236     static iconv_t iconv_h = (iconv_t) - 1;
00237 
00238     if (g_iconv_works)
00239     {
00240         if (iconv_h == (iconv_t) - 1)
00241         {
00242             if ((iconv_h = iconv_open(g_codepage, WINDOWS_CODEPAGE)) == (iconv_t) - 1)
00243             {
00244                 warning("rdp_in_unistr: iconv_open[%s -> %s] fail %d\n",
00245                     WINDOWS_CODEPAGE, g_codepage, (int) iconv_h);
00246 
00247                 g_iconv_works = False;
00248                 return rdp_in_unistr(s, string, uni_len);
00249             }
00250         }
00251 
00252         if (iconv(iconv_h, (ICONV_CONST char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
00253         {
00254             iconv_close(iconv_h);
00255             iconv_h = (iconv_t) - 1;
00256             warning("rdp_in_unistr: iconv fail, errno %d\n", errno);
00257 
00258             g_iconv_works = False;
00259             return rdp_in_unistr(s, string, uni_len);
00260         }
00261 
00262         /* we must update the location of the current STREAM for future reads of s->p */
00263         s->p += uni_len;
00264 
00265         return pout - string;
00266     }
00267     else
00268 #endif
00269     {
00270         int i = 0;
00271 
00272         while (i < uni_len / 2)
00273         {
00274             in_uint8a(s, &string[i++], 1);
00275             in_uint8s(s, 1);
00276         }
00277 
00278         return i - 1;
00279     }
00280 }
00281 
00282 
00283 /* Parse a logon info packet */
00284 static void
00285 rdp_send_logon_info(uint32 flags, char *domain, char *user,
00286             char *password, char *program, char *directory)
00287 {
00288     //char *ipaddr = tcp_get_address();
00289     int len_domain = 2 * strlen(domain);
00290     int len_user = 2 * strlen(user);
00291     int len_password = 2 * strlen(password);
00292     int len_program = 2 * strlen(program);
00293     int len_directory = 2 * strlen(directory);
00294     //int len_ip = 2 * strlen(ipaddr);
00295     //int len_dll = 2 * strlen("C:\\WINNT\\System32\\mstscax.dll");
00296     //int packetlen = 0;
00297     uint32 sec_flags = g_encryption ? (SEC_LOGON_INFO | SEC_ENCRYPT) : SEC_LOGON_INFO;
00298     STREAM s = NULL;
00299     //time_t t = time(NULL);
00300     //time_t tzone;
00301 
00302     if (!g_use_rdp5 || 1 == g_server_rdp_version)
00303     {
00304         DEBUG_RDP5(("Sending RDP4-style Logon packet\n"));
00305 
00306         s = sec_init(sec_flags, 18 + len_domain + len_user + len_password
00307                  + len_program + len_directory + 10);
00308 
00309         out_uint32(s, 0);
00310         out_uint32_le(s, flags);
00311         out_uint16_le(s, len_domain);
00312         out_uint16_le(s, len_user);
00313         out_uint16_le(s, len_password);
00314         out_uint16_le(s, len_program);
00315         out_uint16_le(s, len_directory);
00316         rdp_out_unistr(s, domain, len_domain);
00317         rdp_out_unistr(s, user, len_user);
00318         rdp_out_unistr(s, password, len_password);
00319         rdp_out_unistr(s, program, len_program);
00320         rdp_out_unistr(s, directory, len_directory);
00321     }
00322     else
00323     {
00324 #if 0
00325         flags |= RDP_LOGON_BLOB;
00326         DEBUG_RDP5(("Sending RDP5-style Logon packet\n"));
00327         packetlen = 4 + /* Unknown uint32 */
00328             4 + /* flags */
00329             2 + /* len_domain */
00330             2 + /* len_user */
00331             (flags & RDP_LOGON_AUTO ? 2 : 0) +  /* len_password */
00332             (flags & RDP_LOGON_BLOB ? 2 : 0) +  /* Length of BLOB */
00333             2 + /* len_program */
00334             2 + /* len_directory */
00335             (0 < len_domain ? len_domain : 2) + /* domain */
00336             len_user + (flags & RDP_LOGON_AUTO ? len_password : 0) + 0 +    /* We have no 512 byte BLOB. Perhaps we must? */
00337             (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO) ? 2 : 0) + /* After the BLOB is a unknown int16. If there is a BLOB, that is. */
00338             (0 < len_program ? len_program : 2) + (0 < len_directory ? len_directory : 2) + 2 + /* Unknown (2) */
00339             2 + /* Client ip length */
00340             len_ip +    /* Client ip */
00341             2 + /* DLL string length */
00342             len_dll +   /* DLL string */
00343             2 + /* Unknown */
00344             2 + /* Unknown */
00345             64 +    /* Time zone #0 */
00346             2 + /* Unknown */
00347             64 +    /* Time zone #1 */
00348             32; /* Unknown */
00349 
00350         s = sec_init(sec_flags, packetlen);
00351         DEBUG_RDP5(("Called sec_init with packetlen %d\n", packetlen));
00352 
00353         out_uint32(s, 0);   /* Unknown */
00354         out_uint32_le(s, flags);
00355         out_uint16_le(s, len_domain);
00356         out_uint16_le(s, len_user);
00357         if (flags & RDP_LOGON_AUTO)
00358         {
00359             out_uint16_le(s, len_password);
00360 
00361         }
00362         if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
00363         {
00364             out_uint16_le(s, 0);
00365         }
00366         out_uint16_le(s, len_program);
00367         out_uint16_le(s, len_directory);
00368         if (0 < len_domain)
00369             rdp_out_unistr(s, domain, len_domain);
00370         else
00371             out_uint16_le(s, 0);
00372         rdp_out_unistr(s, user, len_user);
00373         if (flags & RDP_LOGON_AUTO)
00374         {
00375             rdp_out_unistr(s, password, len_password);
00376         }
00377         if (flags & RDP_LOGON_BLOB && !(flags & RDP_LOGON_AUTO))
00378         {
00379             out_uint16_le(s, 0);
00380         }
00381         if (0 < len_program)
00382         {
00383             rdp_out_unistr(s, program, len_program);
00384 
00385         }
00386         else
00387         {
00388             out_uint16_le(s, 0);
00389         }
00390         if (0 < len_directory)
00391         {
00392             rdp_out_unistr(s, directory, len_directory);
00393         }
00394         else
00395         {
00396             out_uint16_le(s, 0);
00397         }
00398         out_uint16_le(s, 2);
00399         out_uint16_le(s, len_ip + 2);   /* Length of client ip */
00400         rdp_out_unistr(s, ipaddr, len_ip);
00401         out_uint16_le(s, len_dll + 2);
00402         rdp_out_unistr(s, "C:\\WINNT\\System32\\mstscax.dll", len_dll);
00403 
00404         tzone = (mktime(gmtime(&t)) - mktime(localtime(&t))) / 60;
00405         out_uint32_le(s, tzone);
00406 
00407         rdp_out_unistr(s, "GTB, normaltid", 2 * strlen("GTB, normaltid"));
00408         out_uint8s(s, 62 - 2 * strlen("GTB, normaltid"));
00409 
00410         out_uint32_le(s, 0x0a0000);
00411         out_uint32_le(s, 0x050000);
00412         out_uint32_le(s, 3);
00413         out_uint32_le(s, 0);
00414         out_uint32_le(s, 0);
00415 
00416         rdp_out_unistr(s, "GTB, sommartid", 2 * strlen("GTB, sommartid"));
00417         out_uint8s(s, 62 - 2 * strlen("GTB, sommartid"));
00418 
00419         out_uint32_le(s, 0x30000);
00420         out_uint32_le(s, 0x050000);
00421         out_uint32_le(s, 2);
00422         out_uint32(s, 0);
00423         out_uint32_le(s, 0xffffffc4);
00424         out_uint32_le(s, 0xfffffffe);
00425         out_uint32_le(s, g_rdp5_performanceflags);
00426         out_uint32(s, 0);
00427 
00428 #endif
00429     }
00430     s_mark_end(s);
00431     sec_send(s, sec_flags);
00432 }
00433 
00434 /* Send a control PDU */
00435 static void
00436 rdp_send_control(uint16 action)
00437 {
00438     STREAM s;
00439 
00440     s = rdp_init_data(8);
00441 
00442     out_uint16_le(s, action);
00443     out_uint16(s, 0);   /* userid */
00444     out_uint32(s, 0);   /* control id */
00445 
00446     s_mark_end(s);
00447     rdp_send_data(s, RDP_DATA_PDU_CONTROL);
00448 }
00449 
00450 /* Send a synchronisation PDU */
00451 static void
00452 rdp_send_synchronise(void)
00453 {
00454     STREAM s;
00455 
00456     s = rdp_init_data(4);
00457 
00458     out_uint16_le(s, 1);    /* type */
00459     out_uint16_le(s, 1002);
00460 
00461     s_mark_end(s);
00462     rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
00463 }
00464 
00465 /* Send a single input event */
00466 void
00467 rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
00468 {
00469     STREAM s;
00470 
00471     s = rdp_init_data(16);
00472 
00473     out_uint16_le(s, 1);    /* number of events */
00474     out_uint16(s, 0);   /* pad */
00475 
00476     out_uint32_le(s, time);
00477     out_uint16_le(s, message_type);
00478     out_uint16_le(s, device_flags);
00479     out_uint16_le(s, param1);
00480     out_uint16_le(s, param2);
00481 
00482     s_mark_end(s);
00483     rdp_send_data(s, RDP_DATA_PDU_INPUT);
00484 }
00485 
00486 /* Send a client window information PDU */
00487 void
00488 rdp_send_client_window_status(int status)
00489 {
00490     STREAM s;
00491     static int current_status = 1;
00492 
00493     if (current_status == status)
00494         return;
00495 
00496     s = rdp_init_data(12);
00497 
00498     out_uint32_le(s, status);
00499 
00500     switch (status)
00501     {
00502         case 0: /* shut the server up */
00503             break;
00504 
00505         case 1: /* receive data again */
00506             out_uint32_le(s, 0);    /* unknown */
00507             out_uint16_le(s, g_width);
00508             out_uint16_le(s, g_height);
00509             break;
00510     }
00511 
00512     s_mark_end(s);
00513     rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
00514     current_status = status;
00515 }
00516 
00517 /* Send persistent bitmap cache enumeration PDU's */
00518 static void
00519 rdp_enum_bmpcache2(void)
00520 {
00521     STREAM s;
00522     HASH_KEY keylist[BMPCACHE2_NUM_PSTCELLS];
00523     uint32 num_keys, offset, count, flags;
00524 
00525     offset = 0;
00526     num_keys = pstcache_enumerate(2, keylist);
00527 
00528     while (offset < num_keys)
00529     {
00530         count = MIN(num_keys - offset, 169);
00531 
00532         s = rdp_init_data(24 + count * sizeof(HASH_KEY));
00533 
00534         flags = 0;
00535         if (offset == 0)
00536             flags |= PDU_FLAG_FIRST;
00537         if (num_keys - offset <= 169)
00538             flags |= PDU_FLAG_LAST;
00539 
00540         /* header */
00541         out_uint32_le(s, 0);
00542         out_uint16_le(s, count);
00543         out_uint16_le(s, 0);
00544         out_uint16_le(s, 0);
00545         out_uint16_le(s, 0);
00546         out_uint16_le(s, 0);
00547         out_uint16_le(s, num_keys);
00548         out_uint32_le(s, 0);
00549         out_uint32_le(s, flags);
00550 
00551         /* list */
00552         out_uint8a(s, keylist[offset], count * sizeof(HASH_KEY));
00553 
00554         s_mark_end(s);
00555         rdp_send_data(s, 0x2b);
00556 
00557         offset += 169;
00558     }
00559 }
00560 
00561 /* Send an (empty) font information PDU */
00562 static void
00563 rdp_send_fonts(uint16 seq)
00564 {
00565     STREAM s;
00566 
00567     s = rdp_init_data(8);
00568 
00569     out_uint16(s, 0);   /* number of fonts */
00570     out_uint16_le(s, 0);    /* pad? */
00571     out_uint16_le(s, seq);  /* unknown */
00572     out_uint16_le(s, 0x32); /* entry size */
00573 
00574     s_mark_end(s);
00575     rdp_send_data(s, RDP_DATA_PDU_FONT2);
00576 }
00577 
00578 /* Output general capability set */
00579 static void
00580 rdp_out_general_caps(STREAM s)
00581 {
00582     out_uint16_le(s, RDP_CAPSET_GENERAL);
00583     out_uint16_le(s, RDP_CAPLEN_GENERAL);
00584 
00585     out_uint16_le(s, 1);    /* OS major type */
00586     out_uint16_le(s, 3);    /* OS minor type */
00587     out_uint16_le(s, 0x200);    /* Protocol version */
00588     out_uint16(s, 0);   /* Pad */
00589     out_uint16(s, 0);   /* Compression types */
00590     out_uint16_le(s, g_use_rdp5 ? 0x40d : 0);
00591     /* Pad, according to T.128. 0x40d seems to 
00592        trigger
00593        the server to start sending RDP5 packets. 
00594        However, the value is 0x1d04 with W2KTSK and
00595        NT4MS. Hmm.. Anyway, thankyou, Microsoft,
00596        for sending such information in a padding 
00597        field.. */
00598     out_uint16(s, 0);   /* Update capability */
00599     out_uint16(s, 0);   /* Remote unshare capability */
00600     out_uint16(s, 0);   /* Compression level */
00601     out_uint16(s, 0);   /* Pad */
00602 }
00603 
00604 /* Output bitmap capability set */
00605 static void
00606 rdp_out_bitmap_caps(STREAM s)
00607 {
00608     out_uint16_le(s, RDP_CAPSET_BITMAP);
00609     out_uint16_le(s, RDP_CAPLEN_BITMAP);
00610 
00611     out_uint16_le(s, g_server_depth);   /* Preferred colour depth */
00612     out_uint16_le(s, 1);    /* Receive 1 BPP */
00613     out_uint16_le(s, 1);    /* Receive 4 BPP */
00614     out_uint16_le(s, 1);    /* Receive 8 BPP */
00615     out_uint16_le(s, 800);  /* Desktop width */
00616     out_uint16_le(s, 600);  /* Desktop height */
00617     out_uint16(s, 0);   /* Pad */
00618     out_uint16(s, 1);   /* Allow resize */
00619     out_uint16_le(s, g_bitmap_compression ? 1 : 0); /* Support compression */
00620     out_uint16(s, 0);   /* Unknown */
00621     out_uint16_le(s, 1);    /* Unknown */
00622     out_uint16(s, 0);   /* Pad */
00623 }
00624 
00625 /* Output order capability set */
00626 static void
00627 rdp_out_order_caps(STREAM s)
00628 {
00629     uint8 order_caps[32];
00630 
00631     memset(order_caps, 0, 32);
00632     order_caps[0] = 1;  /* dest blt */
00633     order_caps[1] = 1;  /* pat blt */
00634     order_caps[2] = 1;  /* screen blt */
00635     order_caps[3] = (g_bitmap_cache ? 1 : 0);   /* memblt */
00636     order_caps[4] = 0;  /* triblt */
00637     order_caps[8] = 1;  /* line */
00638     order_caps[9] = 1;  /* line */
00639     order_caps[10] = 1; /* rect */
00640     order_caps[11] = (g_desktop_save ? 1 : 0);  /* desksave */
00641     order_caps[13] = 1; /* memblt */
00642     order_caps[14] = 1; /* triblt */
00643     order_caps[20] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon */
00644     order_caps[21] = (g_polygon_ellipse_orders ? 1 : 0);    /* polygon2 */
00645     order_caps[22] = 1; /* polyline */
00646     order_caps[25] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse */
00647     order_caps[26] = (g_polygon_ellipse_orders ? 1 : 0);    /* ellipse2 */
00648     order_caps[27] = 1; /* text2 */
00649     out_uint16_le(s, RDP_CAPSET_ORDER);
00650     out_uint16_le(s, RDP_CAPLEN_ORDER);
00651 
00652     out_uint8s(s, 20);  /* Terminal desc, pad */
00653     out_uint16_le(s, 1);    /* Cache X granularity */
00654     out_uint16_le(s, 20);   /* Cache Y granularity */
00655     out_uint16(s, 0);   /* Pad */
00656     out_uint16_le(s, 1);    /* Max order level */
00657     out_uint16_le(s, 0x147);    /* Number of fonts */
00658     out_uint16_le(s, 0x2a); /* Capability flags */
00659     out_uint8p(s, order_caps, 32);  /* Orders supported */
00660     out_uint16_le(s, 0x6a1);    /* Text capability flags */
00661     out_uint8s(s, 6);   /* Pad */
00662     out_uint32_le(s, g_desktop_save == False ? 0 : 0x38400);    /* Desktop cache size */
00663     out_uint32(s, 0);   /* Unknown */
00664     out_uint32_le(s, 0x4e4);    /* Unknown */
00665 }
00666 
00667 /* Output bitmap cache capability set */
00668 static void
00669 rdp_out_bmpcache_caps(STREAM s)
00670 {
00671     int Bpp;
00672     out_uint16_le(s, RDP_CAPSET_BMPCACHE);
00673     out_uint16_le(s, RDP_CAPLEN_BMPCACHE);
00674 
00675     Bpp = (g_server_depth + 7) / 8; /* bytes per pixel */
00676     out_uint8s(s, 24);  /* unused */
00677     out_uint16_le(s, 0x258);    /* entries */
00678     out_uint16_le(s, 0x100 * Bpp);  /* max cell size */
00679     out_uint16_le(s, 0x12c);    /* entries */
00680     out_uint16_le(s, 0x400 * Bpp);  /* max cell size */
00681     out_uint16_le(s, 0x106);    /* entries */
00682     out_uint16_le(s, 0x1000 * Bpp); /* max cell size */
00683 }
00684 
00685 /* Output bitmap cache v2 capability set */
00686 static void
00687 rdp_out_bmpcache2_caps(STREAM s)
00688 {
00689     out_uint16_le(s, RDP_CAPSET_BMPCACHE2);
00690     out_uint16_le(s, RDP_CAPLEN_BMPCACHE2);
00691 
00692     out_uint16_le(s, g_bitmap_cache_persist_enable ? 2 : 0);    /* version */
00693 
00694     out_uint16_be(s, 3);    /* number of caches in this set */
00695 
00696     /* max cell size for cache 0 is 16x16, 1 = 32x32, 2 = 64x64, etc */
00697     out_uint32_le(s, BMPCACHE2_C0_CELLS);
00698     out_uint32_le(s, BMPCACHE2_C1_CELLS);
00699     if (pstcache_init(2))
00700     {
00701         out_uint32_le(s, BMPCACHE2_NUM_PSTCELLS | BMPCACHE2_FLAG_PERSIST);
00702     }
00703     else
00704     {
00705         out_uint32_le(s, BMPCACHE2_C2_CELLS);
00706     }
00707     out_uint8s(s, 20);  /* other bitmap caches not used */
00708 }
00709 
00710 /* Output control capability set */
00711 static void
00712 rdp_out_control_caps(STREAM s)
00713 {
00714     out_uint16_le(s, RDP_CAPSET_CONTROL);
00715     out_uint16_le(s, RDP_CAPLEN_CONTROL);
00716 
00717     out_uint16(s, 0);   /* Control capabilities */
00718     out_uint16(s, 0);   /* Remote detach */
00719     out_uint16_le(s, 2);    /* Control interest */
00720     out_uint16_le(s, 2);    /* Detach interest */
00721 }
00722 
00723 /* Output activation capability set */
00724 static void
00725 rdp_out_activate_caps(STREAM s)
00726 {
00727     out_uint16_le(s, RDP_CAPSET_ACTIVATE);
00728     out_uint16_le(s, RDP_CAPLEN_ACTIVATE);
00729 
00730     out_uint16(s, 0);   /* Help key */
00731     out_uint16(s, 0);   /* Help index key */
00732     out_uint16(s, 0);   /* Extended help key */
00733     out_uint16(s, 0);   /* Window activate */
00734 }
00735 
00736 /* Output pointer capability set */
00737 static void
00738 rdp_out_pointer_caps(STREAM s)
00739 {
00740     out_uint16_le(s, RDP_CAPSET_POINTER);
00741     out_uint16_le(s, RDP_CAPLEN_POINTER);
00742 
00743     out_uint16(s, 0);   /* Colour pointer */
00744     out_uint16_le(s, 20);   /* Cache size */
00745 }
00746 
00747 /* Output share capability set */
00748 static void
00749 rdp_out_share_caps(STREAM s)
00750 {
00751     out_uint16_le(s, RDP_CAPSET_SHARE);
00752     out_uint16_le(s, RDP_CAPLEN_SHARE);
00753 
00754     out_uint16(s, 0);   /* userid */
00755     out_uint16(s, 0);   /* pad */
00756 }
00757 
00758 /* Output colour cache capability set */
00759 static void
00760 rdp_out_colcache_caps(STREAM s)
00761 {
00762     out_uint16_le(s, RDP_CAPSET_COLCACHE);
00763     out_uint16_le(s, RDP_CAPLEN_COLCACHE);
00764 
00765     out_uint16_le(s, 6);    /* cache size */
00766     out_uint16(s, 0);   /* pad */
00767 }
00768 
00769 static uint8 caps_0x0d[] = {
00770     0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00,
00771     0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00772     0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00774     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00775     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00776     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00777     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00778     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00779     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00780     0x00, 0x00, 0x00, 0x00
00781 };
00782 
00783 static uint8 caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 };
00784 
00785 static uint8 caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 };
00786 
00787 static uint8 caps_0x10[] = {
00788     0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00,
00789     0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00,
00790     0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00,
00791     0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00,
00792     0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08,
00793     0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00
00794 };
00795 
00796 /* Output unknown capability sets */
00797 static void
00798 rdp_out_unknown_caps(STREAM s, uint16 id, uint16 length, uint8 * caps)
00799 {
00800     out_uint16_le(s, id);
00801     out_uint16_le(s, length);
00802 
00803     out_uint8p(s, caps, length - 4);
00804 }
00805 
00806 #define RDP5_FLAG 0x0030
00807 /* Send a confirm active PDU */
00808 static void
00809 rdp_send_confirm_active(void)
00810 {
00811     STREAM s;
00812     uint32 sec_flags = g_encryption ? (RDP5_FLAG | SEC_ENCRYPT) : RDP5_FLAG;
00813     uint16 caplen =
00814         RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER +
00815         RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE +
00816         RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL +
00817         RDP_CAPLEN_POINTER + RDP_CAPLEN_SHARE +
00818         0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */  +
00819         4 /* w2k fix, why? */ ;
00820 
00821     s = sec_init(sec_flags, 6 + 14 + caplen + sizeof(RDP_SOURCE));
00822 
00823     out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE));
00824     out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10));  /* Version 1 */
00825     out_uint16_le(s, (g_mcs_userid + 1001));
00826 
00827     out_uint32_le(s, g_rdp_shareid);
00828     out_uint16_le(s, 0x3ea);    /* userid */
00829     out_uint16_le(s, sizeof(RDP_SOURCE));
00830     out_uint16_le(s, caplen);
00831 
00832     out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
00833     out_uint16_le(s, 0xd);  /* num_caps */
00834     out_uint8s(s, 2);   /* pad */
00835 
00836     rdp_out_general_caps(s);
00837     rdp_out_bitmap_caps(s);
00838     rdp_out_order_caps(s);
00839     g_use_rdp5 ? rdp_out_bmpcache2_caps(s) : rdp_out_bmpcache_caps(s);
00840     rdp_out_colcache_caps(s);
00841     rdp_out_activate_caps(s);
00842     rdp_out_control_caps(s);
00843     rdp_out_pointer_caps(s);
00844     rdp_out_share_caps(s);
00845 
00846     rdp_out_unknown_caps(s, 0x0d, 0x58, caps_0x0d); /* international? */
00847     rdp_out_unknown_caps(s, 0x0c, 0x08, caps_0x0c);
00848     rdp_out_unknown_caps(s, 0x0e, 0x08, caps_0x0e);
00849     rdp_out_unknown_caps(s, 0x10, 0x34, caps_0x10); /* glyph cache? */
00850 
00851     s_mark_end(s);
00852     sec_send(s, sec_flags);
00853 }
00854 
00855 /* Process a general capability set */
00856 static void
00857 rdp_process_general_caps(STREAM s)
00858 {
00859     uint16 pad2octetsB; /* rdp5 flags? */
00860 
00861     in_uint8s(s, 10);
00862     in_uint16_le(s, pad2octetsB);
00863 
00864     if (!pad2octetsB)
00865         g_use_rdp5 = False;
00866 }
00867 
00868 /* Process a bitmap capability set */
00869 static void
00870 rdp_process_bitmap_caps(STREAM s)
00871 {
00872     uint16 width, height, depth;
00873 
00874     in_uint16_le(s, depth);
00875     in_uint8s(s, 6);
00876 
00877     in_uint16_le(s, width);
00878     in_uint16_le(s, height);
00879 
00880     DEBUG(("setting desktop size and depth to: %dx%dx%d\n", width, height, depth));
00881 
00882     /*
00883      * The server may limit depth and change the size of the desktop (for
00884      * example when shadowing another session).
00885      */
00886     if (g_server_depth != depth)
00887     {
00888         warning("Remote desktop does not support colour depth %d; falling back to %d\n",
00889             g_server_depth, depth);
00890         g_server_depth = depth;
00891     }
00892     if (g_width != width || g_height != height)
00893     {
00894         warning("Remote desktop changed from %dx%d to %dx%d.\n", g_width, g_height,
00895             width, height);
00896         g_width = width;
00897         g_height = height;
00898         ui_resize_window();
00899     }
00900 }
00901 
00902 /* Process server capabilities */
00903 static void
00904 rdp_process_server_caps(STREAM s, uint16 length)
00905 {
00906     int n;
00907     uint8 *next, *start;
00908     uint16 ncapsets, capset_type, capset_length;
00909 
00910     start = s->p;
00911 
00912     in_uint16_le(s, ncapsets);
00913     in_uint8s(s, 2);    /* pad */
00914 
00915     for (n = 0; n < ncapsets; n++)
00916     {
00917         if (s->p > start + length)
00918             return;
00919 
00920         in_uint16_le(s, capset_type);
00921         in_uint16_le(s, capset_length);
00922 
00923         next = s->p + capset_length - 4;
00924 
00925         switch (capset_type)
00926         {
00927             case RDP_CAPSET_GENERAL:
00928                 rdp_process_general_caps(s);
00929                 break;
00930 
00931             case RDP_CAPSET_BITMAP:
00932                 rdp_process_bitmap_caps(s);
00933                 break;
00934         }
00935 
00936         s->p = next;
00937     }
00938 }
00939 
00940 /* Respond to a demand active PDU */
00941 static void
00942 process_demand_active(STREAM s)
00943 {
00944     uint8 type;
00945     uint16 len_src_descriptor, len_combined_caps;
00946 
00947     in_uint32_le(s, g_rdp_shareid);
00948     in_uint16_le(s, len_src_descriptor);
00949     in_uint16_le(s, len_combined_caps);
00950     in_uint8s(s, len_src_descriptor);
00951 
00952     DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid));
00953     rdp_process_server_caps(s, len_combined_caps);
00954 
00955     rdp_send_confirm_active();
00956     rdp_send_synchronise();
00957     rdp_send_control(RDP_CTL_COOPERATE);
00958     rdp_send_control(RDP_CTL_REQUEST_CONTROL);
00959     rdp_recv(&type);    /* RDP_PDU_SYNCHRONIZE */
00960     rdp_recv(&type);    /* RDP_CTL_COOPERATE */
00961     rdp_recv(&type);    /* RDP_CTL_GRANT_CONTROL */
00962     rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(read_keyboard_state()), 0);
00963 
00964     if (g_use_rdp5)
00965     {
00966         rdp_enum_bmpcache2();
00967         rdp_send_fonts(3);
00968     }
00969     else
00970     {
00971         rdp_send_fonts(1);
00972         rdp_send_fonts(2);
00973     }
00974 
00975     rdp_recv(&type);    /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */
00976     reset_order_state();
00977 }
00978 
00979 /* Process a colour pointer PDU */
00980 void
00981 process_colour_pointer_pdu(STREAM s)
00982 {
00983     uint16 x, y, width, height, cache_idx, masklen, datalen;
00984     uint8 *mask, *data;
00985     HCURSOR cursor;
00986 
00987     in_uint16_le(s, cache_idx);
00988     in_uint16_le(s, x);
00989     in_uint16_le(s, y);
00990     in_uint16_le(s, width);
00991     in_uint16_le(s, height);
00992     in_uint16_le(s, masklen);
00993     in_uint16_le(s, datalen);
00994     in_uint8p(s, data, datalen);
00995     in_uint8p(s, mask, masklen);
00996     cursor = ui_create_cursor(x, y, width, height, mask, data);
00997     ui_set_cursor(cursor);
00998     cache_put_cursor(cache_idx, cursor);
00999 }
01000 
01001 /* Process a cached pointer PDU */
01002 void
01003 process_cached_pointer_pdu(STREAM s)
01004 {
01005     uint16 cache_idx;
01006 
01007     in_uint16_le(s, cache_idx);
01008     ui_set_cursor(cache_get_cursor(cache_idx));
01009 }
01010 
01011 /* Process a system pointer PDU */
01012 void
01013 process_system_pointer_pdu(STREAM s)
01014 {
01015     uint16 system_pointer_type;
01016 
01017     in_uint16(s, system_pointer_type);
01018     switch (system_pointer_type)
01019     {
01020         case RDP_NULL_POINTER:
01021             ui_set_null_cursor();
01022             break;
01023 
01024         default:
01025             unimpl("System pointer message 0x%x\n", system_pointer_type);
01026     }
01027 }
01028 
01029 /* Process a pointer PDU */
01030 static void
01031 process_pointer_pdu(STREAM s)
01032 {
01033     uint16 message_type;
01034     uint16 x, y;
01035 
01036     in_uint16_le(s, message_type);
01037     in_uint8s(s, 2);    /* pad */
01038 
01039     switch (message_type)
01040     {
01041         case RDP_POINTER_MOVE:
01042             in_uint16_le(s, x);
01043             in_uint16_le(s, y);
01044             if (s_check(s))
01045                 ui_move_pointer(x, y);
01046             break;
01047 
01048         case RDP_POINTER_COLOR:
01049             process_colour_pointer_pdu(s);
01050             break;
01051 
01052         case RDP_POINTER_CACHED:
01053             process_cached_pointer_pdu(s);
01054             break;
01055 
01056         case RDP_POINTER_SYSTEM:
01057             process_system_pointer_pdu(s);
01058             break;
01059 
01060         default:
01061             unimpl("Pointer message 0x%x\n", message_type);
01062     }
01063 }
01064 
01065 /* Process bitmap updates */
01066 void
01067 process_bitmap_updates(STREAM s)
01068 {
01069     uint16 num_updates;
01070     uint16 left, top, right, bottom, width, height;
01071     uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
01072     uint8 *data, *bmpdata;
01073     int i;
01074 
01075     in_uint16_le(s, num_updates);
01076 
01077     for (i = 0; i < num_updates; i++)
01078     {
01079         in_uint16_le(s, left);
01080         in_uint16_le(s, top);
01081         in_uint16_le(s, right);
01082         in_uint16_le(s, bottom);
01083         in_uint16_le(s, width);
01084         in_uint16_le(s, height);
01085         in_uint16_le(s, bpp);
01086         Bpp = (bpp + 7) / 8;
01087         in_uint16_le(s, compress);
01088         in_uint16_le(s, bufsize);
01089 
01090         cx = right - left + 1;
01091         cy = bottom - top + 1;
01092 
01093         DEBUG(("BITMAP_UPDATE(l=%d,t=%d,r=%d,b=%d,w=%d,h=%d,Bpp=%d,cmp=%d)\n",
01094                left, top, right, bottom, width, height, Bpp, compress));
01095 
01096         if (!compress)
01097         {
01098             int y;
01099             bmpdata = (uint8 *) xmalloc(width * height * Bpp);
01100             for (y = 0; y < height; y++)
01101             {
01102                 in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
01103                       width * Bpp);
01104             }
01105             ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
01106             xfree(bmpdata);
01107             continue;
01108         }
01109 
01110 
01111         if (compress & 0x400)
01112         {
01113             size = bufsize;
01114         }
01115         else
01116         {
01117             in_uint8s(s, 2);    /* pad */
01118             in_uint16_le(s, size);
01119             in_uint8s(s, 4);    /* line_size, final_size */
01120         }
01121         in_uint8p(s, data, size);
01122         bmpdata = (uint8 *) xmalloc(width * height * Bpp);
01123         if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
01124         {
01125             ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
01126         }
01127         else
01128         {
01129             DEBUG_RDP5(("Failed to decompress data\n"));
01130         }
01131 
01132         xfree(bmpdata);
01133     }
01134 }
01135 
01136 /* Process a palette update */
01137 void
01138 process_palette(STREAM s)
01139 {
01140     COLOURENTRY *entry;
01141     COLOURMAP map;
01142     RD_HCOLOURMAP hmap;
01143     int i;
01144 
01145     in_uint8s(s, 2);    /* pad */
01146     in_uint16_le(s, map.ncolours);
01147     in_uint8s(s, 2);    /* pad */
01148 
01149     map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
01150 
01151     DEBUG(("PALETTE(c=%d)\n", map.ncolours));
01152 
01153     for (i = 0; i < map.ncolours; i++)
01154     {
01155         entry = &map.colours[i];
01156         in_uint8(s, entry->red);
01157         in_uint8(s, entry->green);
01158         in_uint8(s, entry->blue);
01159     }
01160 
01161     hmap = ui_create_colourmap(&map);
01162     ui_set_colourmap(hmap);
01163 
01164     xfree(map.colours);
01165 }
01166 
01167 /* Process an update PDU */
01168 static void
01169 process_update_pdu(STREAM s)
01170 {
01171     uint16 update_type, count;
01172 
01173     in_uint16_le(s, update_type);
01174 
01175     ui_begin_update();
01176     switch (update_type)
01177     {
01178         case RDP_UPDATE_ORDERS:
01179             in_uint8s(s, 2);    /* pad */
01180             in_uint16_le(s, count);
01181             in_uint8s(s, 2);    /* pad */
01182             process_orders(s, count);
01183             break;
01184 
01185         case RDP_UPDATE_BITMAP:
01186             process_bitmap_updates(s);
01187             break;
01188 
01189         case RDP_UPDATE_PALETTE:
01190             process_palette(s);
01191             break;
01192 
01193         case RDP_UPDATE_SYNCHRONIZE:
01194             break;
01195 
01196         default:
01197             unimpl("update %d\n", update_type);
01198     }
01199     ui_end_update();
01200 }
01201 
01202 /* Process a disconnect PDU */
01203 void
01204 process_disconnect_pdu(STREAM s, uint32 * ext_disc_reason)
01205 {
01206     in_uint32_le(s, *ext_disc_reason);
01207 
01208     DEBUG(("Received disconnect PDU\n"));
01209 }
01210 
01211 /* Process data PDU */
01212 static BOOL
01213 process_data_pdu(STREAM s, uint32 * ext_disc_reason)
01214 {
01215     uint8 data_pdu_type;
01216     uint8 ctype;
01217     uint16 clen;
01218     uint32 len;
01219 
01220     uint32 roff, rlen;
01221 
01222     struct stream *ns = &(g_mppc_dict.ns);
01223 
01224     in_uint8s(s, 6);    /* shareid, pad, streamid */
01225     in_uint16(s, len);
01226     in_uint8(s, data_pdu_type);
01227     in_uint8(s, ctype);
01228     in_uint16(s, clen);
01229     clen -= 18;
01230 
01231     if (ctype & RDP_MPPC_COMPRESSED)
01232     {
01233         if (len > RDP_MPPC_DICT_SIZE)
01234             error("error decompressed packet size exceeds max\n");
01235         if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
01236             error("error while decompressing packet\n");
01237 
01238         /* len -= 18; */
01239 
01240         /* allocate memory and copy the uncompressed data into the temporary stream */
01241         ns->data = (uint8 *) xrealloc(ns->data, rlen);
01242 
01243         memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
01244 
01245         ns->size = rlen;
01246         ns->end = (ns->data + ns->size);
01247         ns->p = ns->data;
01248         ns->rdp_hdr = ns->p;
01249 
01250         s = ns;
01251     }
01252 
01253     switch (data_pdu_type)
01254     {
01255         case RDP_DATA_PDU_UPDATE:
01256             process_update_pdu(s);
01257             break;
01258 
01259         case RDP_DATA_PDU_CONTROL:
01260             DEBUG(("Received Control PDU\n"));
01261             break;
01262 
01263         case RDP_DATA_PDU_SYNCHRONISE:
01264             DEBUG(("Received Sync PDU\n"));
01265             break;
01266 
01267         case RDP_DATA_PDU_POINTER:
01268             process_pointer_pdu(s);
01269             break;
01270 
01271         case RDP_DATA_PDU_BELL:
01272             ui_bell();
01273             break;
01274 
01275         case RDP_DATA_PDU_LOGON:
01276             DEBUG(("Received Logon PDU\n"));
01277             /* User logged on */
01278             break;
01279 
01280         case RDP_DATA_PDU_DISCONNECT:
01281             process_disconnect_pdu(s, ext_disc_reason);
01282             return True;
01283 
01284         default:
01285             unimpl("data PDU %d\n", data_pdu_type);
01286     }
01287     return False;
01288 }
01289 
01290 /* Process redirect PDU from Session Directory */
01291 static BOOL
01292 process_redirect_pdu(STREAM s /*, uint32 * ext_disc_reason */ )
01293 {
01294     uint32 len;
01295 
01296     /* these 2 bytes are unknown, seem to be zeros */
01297     in_uint8s(s, 2);
01298 
01299     /* read connection flags */
01300     in_uint32_le(s, g_redirect_flags);
01301 
01302     /* read length of ip string */
01303     in_uint32_le(s, len);
01304 
01305     /* read ip string */
01306     rdp_in_unistr(s, g_redirect_server, len);
01307 
01308     /* read length of cookie string */
01309     in_uint32_le(s, len);
01310 
01311     /* read cookie string (plain ASCII) */
01312     in_uint8a(s, g_redirect_cookie, len);
01313     g_redirect_cookie[len] = 0;
01314 
01315     /* read length of username string */
01316     in_uint32_le(s, len);
01317 
01318     /* read username string */
01319     rdp_in_unistr(s, g_redirect_username, len);
01320 
01321     /* read length of domain string */
01322     in_uint32_le(s, len);
01323 
01324     /* read domain string */
01325     rdp_in_unistr(s, g_redirect_domain, len);
01326 
01327     /* read length of password string */
01328     in_uint32_le(s, len);
01329 
01330     /* read password string */
01331     rdp_in_unistr(s, g_redirect_password, len);
01332 
01333     g_redirect = True;
01334 
01335     return True;
01336 }
01337 
01338 /* Process incoming packets */
01339 /* nevers gets out of here till app is done */
01340 void
01341 rdp_main_loop(BOOL * deactivated, uint32 * ext_disc_reason)
01342 {
01343     while (rdp_loop(deactivated, ext_disc_reason))
01344         ;
01345 }
01346 
01347 /* used in uiports and rdp_main_loop, processes the rdp packets waiting */
01348 BOOL
01349 rdp_loop(BOOL * deactivated, uint32 * ext_disc_reason)
01350 {
01351     uint8 type;
01352     BOOL disc = False;  /* True when a disconnect PDU was received */
01353     BOOL cont = True;
01354     STREAM s;
01355 
01356     while (cont)
01357     {
01358         s = rdp_recv(&type);
01359         if (s == NULL)
01360             return False;
01361         switch (type)
01362         {
01363             case RDP_PDU_DEMAND_ACTIVE:
01364                 process_demand_active(s);
01365                 *deactivated = False;
01366                 break;
01367             case RDP_PDU_DEACTIVATE:
01368                 DEBUG(("RDP_PDU_DEACTIVATE\n"));
01369                 *deactivated = True;
01370                 break;
01371             case RDP_PDU_REDIRECT:
01372                 return process_redirect_pdu(s);
01373                 break;
01374             case RDP_PDU_DATA:
01375                 disc = process_data_pdu(s, ext_disc_reason);
01376                 break;
01377             case 0:
01378                 break;
01379             default:
01380                 unimpl("PDU %d\n", type);
01381         }
01382         if (disc)
01383             return False;
01384         cont = g_next_packet < s->end;
01385     }
01386     return True;
01387 }
01388 
01389 /* Establish a connection up to the RDP layer */
01390 BOOL
01391 rdp_connect(char *server, uint32 flags, char *domain, char *password,
01392         char *command, char *directory)
01393 {
01394     if (!sec_connect(server, g_username))
01395         return False;
01396 
01397     rdp_send_logon_info(flags, domain, g_username, password, command, directory);
01398     return True;
01399 }
01400 
01401 /* Establish a reconnection up to the RDP layer */
01402 BOOL
01403 rdp_reconnect(char *server, uint32 flags, char *domain, char *password,
01404           char *command, char *directory, char *cookie)
01405 {
01406     if (!sec_reconnect(server))
01407         return False;
01408 
01409     rdp_send_logon_info(flags, domain, g_username, password, command, directory);
01410     return True;
01411 }
01412 
01413 /* Called during redirection to reset the state to support redirection */
01414 void
01415 rdp_reset_state(void)
01416 {
01417     g_next_packet = NULL;   /* reset the packet information */
01418     g_rdp_shareid = 0;
01419     sec_reset_state();
01420 }
01421 
01422 /* Disconnect from the RDP layer */
01423 void
01424 rdp_disconnect(void)
01425 {
01426     sec_disconnect();
01427 }

Generated on Sun May 27 2012 04:17:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.